Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 日志线程内存泄漏_Java_Multithreading_Memory Leaks_Thread Safety - Fatal编程技术网

Java 日志线程内存泄漏

Java 日志线程内存泄漏,java,multithreading,memory-leaks,thread-safety,Java,Multithreading,Memory Leaks,Thread Safety,我已经为我的程序编写了一个后台日志线程,如果一个类需要一个记录器,它会从我的线程池中提取它,所以对于每个文件名,只有一个日志正在运行。类,添加任何需要通过日志(字符串)记录的内容 不管怎样,每当我设置登录并在一段时间后运行writetolog()时,我都会遇到HeapOutMemory异常。这是由日志线程造成的,但我看不出内存泄漏在哪里,我也不太擅长线程。我唯一的想法是它在缓冲写入程序中 import java.io.File; import java.io.IOException; impo

我已经为我的程序编写了一个后台日志线程,如果一个类需要一个记录器,它会从我的线程池中提取它,所以对于每个文件名,只有一个日志正在运行。类,添加任何需要通过日志(字符串)记录的内容

不管怎样,每当我设置登录并在一段时间后运行writetolog()时,我都会遇到HeapOutMemory异常。这是由日志线程造成的,但我看不出内存泄漏在哪里,我也不太擅长线程。我唯一的想法是它在缓冲写入程序中

import java.io.File;
import java.io.IOException;

import java.io.FileWriter;
import java.util.Calendar;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Log extends Thread{
private String file;
private BlockingQueue<String> pq = new LinkedBlockingQueue<String>();
private BufferedWriter bw;
private boolean Writing;

@Depreciated
public Log(){
    super();
    file = "log.txt";

    start(); 
}

public Log(ThreadGroup tg, String fileName){
    super(tg,fileName);
    file = fileName;
    try {
        new File(file).createNewFile();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    start(); 
}

public Log(String fileName){
    file = fileName;
    try {
        new File(file).createNewFile();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    start(); 
}

@Override
public void run(){
    //System.out.println("Log Thread booted " +file);

    while(Run.running){
        if (!Writing){
            if(Run.logging)
            writeToLog();
        }
        try{
            Thread.sleep(500);
        }catch(InterruptedException e){
            Thread.currentThread().interrupt();
            break;
        }


    }
    //System.out.println("Log Thread shutting down " +file);
}

public synchronized void log(String s){
    if(Run.logging)
    pq.add(s);
}

private void writeToLog(){
    try{
        Writing = true;

        bw = new BufferedWriter(new FileWriter(file, true));
    while(!pq.isEmpty()){

            bw.write(Calendar.getInstance().getTime().toString() +" " +pq.poll());
            bw.newLine();

    }

    bw.flush();
    bw.close();
    Writing = false;
    }catch(Exception e){Writing = false; e.printStackTrace();}
}



}
导入java.io.File;
导入java.io.IOException;
导入java.io.FileWriter;
导入java.util.Calendar;
导入java.util.concurrent.BlockingQueue;
导入java.util.concurrent.LinkedBlockingQueue;
公共类日志扩展线程{
私有字符串文件;
private BlockingQueue pq=新建LinkedBlockingQueue();
专用缓冲写入程序bw;
私有布尔书写;
@贬值
公共日志(){
超级();
file=“log.txt”;
start();
}
公共日志(线程组tg,字符串文件名){
super(tg,文件名);
文件=文件名;
试一试{
新建文件(File).createNewFile();
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
start();
}
公共日志(字符串文件名){
文件=文件名;
试一试{
新建文件(File).createNewFile();
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
start();
}
@凌驾
公开募捐{
//System.out.println(“日志线程启动”+文件);
while(Run.running){
如果(!写入){
if(Run.logging)
writeToLog();
}
试一试{
睡眠(500);
}捕捉(中断异常e){
Thread.currentThread().interrupt();
打破
}
}
//System.out.println(“日志线程关闭”+文件);
}
公共同步的无效日志(字符串s){
if(Run.logging)
pq.add(s);
}
私有void writeToLog(){
试一试{
写作=真实;
bw=新的BufferedWriter(新的FileWriter(file,true));
而(!pq.isEmpty()){
write(Calendar.getInstance().getTime().toString()+“”+pq.poll());
换行符();
}
bw.flush();
bw.close();
书写=错误;
}catch(异常e){Writing=false;e.printStackTrace();}
}
}
编辑-值得一提的是,在程序的上下文中,它记录了100-1000行

非常感谢
Sam

如果后台线程写入磁盘的速度不够快,则(未指定其容量)将增长,直到它包含
整数.MAX\u值
字符串。这对于java堆大小来说太多了

指定容量,以便在队列已满的情况下,调用log方法的线程将在队列日志的某些部分转储到磁盘时等待:

private BlockingQueue<String> pq = new LinkedBlockingQueue<String>(1000);
private BlockingQueue pq=new LinkedBlockingQueue(1000);
在log方法中使用而不是
add
,以便日志操作等待而不是引发异常


(您注意到在磁盘上写入时间而不是日志记录时间了吗?

如果后台线程写入磁盘的速度不够快,则(未指定其容量)将增长,直到它包含
Integer.MAX\u值
字符串。这对于java堆大小来说太多了

指定容量,以便在队列已满的情况下,调用log方法的线程将在队列日志的某些部分转储到磁盘时等待:

private BlockingQueue<String> pq = new LinkedBlockingQueue<String>(1000);
private BlockingQueue pq=new LinkedBlockingQueue(1000);
在log方法中使用而不是
add
,以便日志操作等待而不是引发异常


(您是否注意到您在磁盘上写入时间而不是在日志中写入时间?

我相信有
专用缓冲写入程序bwas成员变量导致故障。由于您只在
writeToLog()
函数中使用它,因此没有理由将其作为成员变量,每次由多个线程实例化。在函数中创建
BufferedWriter
将在对象超出范围时对其进行GC

private void writeToLog(){ 
    try{ 
        Writing = true; 

        BufferedWriter bw = new BufferedWriter(new FileWriter(file, true)); 
    while(!pq.isEmpty()){ 

            bw.write(Calendar.getInstance().getTime().toString() +" " +pq.poll()); 
            bw.newLine(); 

    } 

    bw.flush(); 
    bw.close(); 
    Writing = false; 
    }catch(Exception e){Writing = false; e.printStackTrace();} 
} 

我相信拥有
private BufferedWriter bwas成员变量导致故障。由于您只在
writeToLog()
函数中使用它,因此没有理由将其作为成员变量,每次由多个线程实例化。在函数中创建
BufferedWriter
将在对象超出范围时对其进行GC

private void writeToLog(){ 
    try{ 
        Writing = true; 

        BufferedWriter bw = new BufferedWriter(new FileWriter(file, true)); 
    while(!pq.isEmpty()){ 

            bw.write(Calendar.getInstance().getTime().toString() +" " +pq.poll()); 
            bw.newLine(); 

    } 

    bw.flush(); 
    bw.close(); 
    Writing = false; 
    }catch(Exception e){Writing = false; e.printStackTrace();} 
} 

我刚刚试过这个,但它仍然运行,好主意我刚试过这个,它仍然运行,好主意是的,这部分解决了我的que溢出的问题,但是,在添加之前,让que清除的正确方法是什么呢?因为现在我得到了一个非法状态异常-队列已满谢谢我现在就快到了,唯一的问题是现在我的blockingqueue似乎马上满了,但里面什么都没有?我的坏消息是我的日志变量已关闭..抱歉,但它正在工作谢谢!很高兴听到:)小心不要让它变得更复杂:在某些情况下,使用现有的日志框架会更明智。是的,这部分解决了我的que溢出的问题,但是,在添加之前,让que清除的正确方法是什么呢?因为现在我得到了一个非法状态异常-队列已满谢谢我现在就快到了,唯一的问题是现在我的blockingqueue似乎马上满了,但里面什么都没有?我的坏消息是我的日志变量已关闭..抱歉,但它正在工作谢谢!很高兴听到:)小心不要让它变得更复杂:在某个时候,使用现有的日志框架会更明智。