码迷,mamicode.com
首页 > 编程语言 > 详细

从ExecutorService的内存溢出谈谈线程池

时间:2020-02-06 14:53:45      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:正在执行   条件   自己的   解决方法   executor   需要   完全   最大   task   

  之前写的一个Sql转发应用出现了内存溢出问题,经过排查发现是ExecutorService没有正确的进行关闭。

  正常来说如果我们将ExecutorService设计成一个静态变量,那么通常我们是不用去管理其是否关闭的,我们只需要对其本身的线程进行维护操作,ExecutorService对象不用我们显示的进行维护操作。但是维护静态线程池对象的不足之处在于,不好去界定池量级的大小,如果太小会导致线程过多的时候线程运行得不到保证,如果过大则通常线程执行时是对内存的一种浪费。所以在调用频率不高的时候,我们往往会在一次调用的时候创建一个ExecutorService,用这个来进行线程池的管理,那么这里就出现了我们遇到的问题,那就是这个ExecutorService其实是需要手动进行关闭的。

 技术图片

 

   上图中ExecutorService就没有正确的关闭。

  为什么ExecutorService不会自己进行回收呢,我们通过对其API的阅读可以得到答案,若是想要ExecutorService完全关闭需要同时满足三个条件:

  1.线程池中没有正在执行的task任务

  2.线程池中没有等待执行的task任务

  3.无法再提交任务到ExecutorService

  显然,如果我们不进行手动关闭的话,第三个条件将无法满足,导致无法其内存无法被回收,而下一次的调用又继续进行了线程池的创建,这样内存迅速的上升,最后导致了OOM。

  那么知道了问题的原因,解决方法其实就比较简单了,我们在使用完之后再调用一个shutdown或者shutdownNow,让线程池状态变成不再能接受线程任务就行了。

  但是这个时候就有了新的问题,如果某个线程阻塞,一直无法关闭,shutdown方法也不能完成自己的使命,但是如果使用shutdownNow方法的话,就会出现关闭的时候还有线程任务没有完成。这个时候要怎么合理的进行线程任务的关闭呢。

  这个时候我们可以设定一个最大超时时间,如果执行shutdown之后经过超时时间还有任务没有结束,那我们就用shutdownNow方法来帮他们上路。

技术图片

 

 

  

从ExecutorService的内存溢出谈谈线程池

标签:正在执行   条件   自己的   解决方法   executor   需要   完全   最大   task   

原文地址:https://www.cnblogs.com/weixiaoS/p/12268370.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!