记录线程内存泄漏

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

无论如何,每当我设置登录并且它运行writetolog()一段时间后我得到heapoutofmemoryexception。 这是由日志线程引起的,但是我无法看到内存泄漏的位置,而且我在线程方面也不是很好。 我唯一的想法是,它是在缓冲的作家?

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 pq = new LinkedBlockingQueue(); 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();} } } 

编辑 – 值得一提的是,在该计划的背景下,它记录了100 – 1000的线

非常感谢Sam

如果后台线程没有足够快地写入磁盘,则LinkedBlockingQueue (其未指定的容量)将增长,直到它包含Integer.MAX_VALUE字符串。 这对你的java堆大小来说太过分了。

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

 private BlockingQueue pq = new LinkedBlockingQueue(1000); 

在日志方法中使用put而不是add ,以便日志记录操作等待而不是抛出exception。

(你是否注意到你在磁盘上写时间而不是记录时间?)

我相信有private BufferedWriter bw; 因为成员变量导致了麻烦。 由于您只在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();} }