2012-09-18 73 views
0

我有一个运行方法的类,并且在类的主要方法定时器调用与该代码的类:的ThreadPoolExecutor OutOfMemoryException异常

Timer timer = new Timer(); 
timer.scheduleAtFixedRate(new LegacySmsSender(), 0, 2*1000); 
在运行方法

,我声明一个ThreadExecutorPool:

ThreadPoolExecutor packetProcessorThreadPool = 
     new ThreadPoolExecutor(4, 
           4, 
           Long.MAX_VALUE, 
           TimeUnit.DAYS, 
           new LinkedBlockingQueue<Runnable>(), 
           new MyThreadFactory("packetProcessorThreadPool") 
           ); 

我创建4个PacketProcessors与new PacketProcessor()packetProcessorThreadPool.submit并保持其Future返回一个列表。那我等他们都在一个循环中完成:

for(Future<?> f:packetProcessorList) 
{ 
    System.out.println("before f.get() "+new Date()); 
    f.get(); 
} 

而那些PacketProcessor类的run方法里面,他们宣布的ThreadPoolExecutor和创建和数量1-5000之间提交线程(其通常创建6-7线程),并在PacketProcessor的ThreadPoolExecutor的代码是这样的:

ThreadPoolExecutor commonThreadPool = 
     new ThreadPoolExecutor(
         20, 
         20, 
         Long.MAX_VALUE, 
         TimeUnit.DAYS, 
         new LinkedBlockingQueue<Runnable>(), 
         new MyThreadFactory("commonThreadPool")); 

,并在结束时,我跑了一段20分钟,我检查的VisualVM,我的内存使用情况和活动​​线程数量的增加,所有的时间。问题是什么 ?

注:请毫不犹豫地问我要更多信息或问题

这里是一些信息截图:

enter image description here

编辑1:

我270 MB的堆转储。我发现了160MB的char []。我发现像1000-20000个查询字符串。我使用StringBuilder构建查询字符串。为什么他们没有得到GCed?

回答

2

执行程序的目的是在应用程序启动时重新声明并重用。否则,您可能只需按需创建单个线程。如果在应用程序执行期间不断创建新的执行程序,则它们的线程将保持运行状态,因此线程数将继续增加。

所以,只需使用DI框架创建执行程序并将它们注入到代码中即可。或者如果它是一个小型项目,请将它们放在静态字段中。

+0

我试图使用它们作为静态,但它根本没有改变这个分析器上的图像。活动线程永不减少的原因是什么? – kommradHomer

1
run方法

,我宣布一个ThreadExecutorPool

如果你在被每2秒,你会得到许多线程在几分钟内执行run方法声明ThreadExecutorPool。

+0

没有。在run方法,我等待线程完成,所以计时器就不会第一个跑'LegacySmsSender'完成 – kommradHomer

+0

你有你的run方法这段代码被执行定期?:的ThreadPoolExecutor packetProcessorThreadPool = 新的ThreadPoolExecutor(前再次启动... – Chobicus

+0

这个代码是在定时器执行 – kommradHomer

0

问题是,你已经告诉你所创建的所有ExecutorService是为了创建线程,然后让它们永远活着。这是在代码非常清楚地明显:

new ThreadPoolExecutor(
         20, 
         20, 
         Long.MAX_VALUE, 
         TimeUnit.DAYS, 
         new LinkedBlockingQueue<Runnable>(), 
         new MyThreadFactory("commonThreadPool")); 

第三个和第四个参数基本上说“保持空闲线程活着(几乎)无限的日子”。你做他们传递任务时的执行情况

  1. 呼叫ExecutorService.shutdown

    您可以在几个方面解决这个问题。

  2. 最好的解决方案是使用单一的ScheduledExecutorService和更合理的任务分配逻辑来限制线程数量并通过阻止线程上下文切换提高性能。
+0

我尝试了数字1的解决方案,并呼吁'shutdown'的热塑性弹性体后,我等待的Future.get S IN的循环。我得到了线程执行的拒绝,然后我尝试数字2,3和TIMEUNIT秒,它并没有改变什么在任何时候都不应该让活线程数量减少? – kommradHomer

+0

如果你得到一个'RejectedExecutionException',然后你在任务被关闭后将任务提交给ExecutorService。随意阅读API。至于线程去,我错了,直到线程池关闭,他们不会死,因为他们是“核心线程”。 –

+0

既设置了“保留IDE线程活着3秒”,也关闭了'commonThreadPool',现在我设法有27个线程住在最大。它在19到27之间变化,但内存使用量仍在不断增加 – kommradHomer

相关问题