关于局部变量的线程池,会不会被回收
遇到个问题,模拟一下,得出结论。
线上监控线程数量一直增加,经过查询是同事在使用线程池没有关闭
伪代码如下
static void test(){
//方法内 定义线程池
ExecutorService pool = new org.apache.tomcat.util.threads.ThreadPoolExecutor(1, 2, 10, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
Executors.defaultThreadFactory(),
new org.apache.tomcat.util.threads.ThreadPoolExecutor.AbortPolicy());
pool.execute(()->{
System.out.println(System.currentTimeMillis());
});
}
在方法里定义线程池,处理任务,每次定时器跑数据,会创建一个线程池,然后处理任务,但是并没有关闭。
模拟
public static void main(String[] args) throws InterruptedException {
while (true){
TimeUnit.SECONDS.sleep(2);
test();
}
未关闭的线程,线程数程线性增长,这里伪代码我还是设置了1个的情况下,不敢想请core,max线程数大的情况以及频繁请求的情况。
局部变量使用线程池一定要关闭
//关闭,等待任务执行结束,工作线程会被打断,没有工作的线程会立即被打断
pool.shutdown();
要么是把线程池设为公共pool,不要再方法里面定义。
然后来看每次请求,关闭线程池的线程数量。
可以看到线程数基本维持不变,能保持平稳。
原因
不适用shutdow 关闭 ,为什么不会被回收?
线程池底层
线程池的原理 ThreadPoolExecutor 当执行一个Runnable时,会先创建一个ThreadPoolExecutor中的内部类Worker对象,将这个Runnable对象作为Worker对象的一个成员变量。
所以 当线程在执行的时候
引用关系如下
ThreadPoolExecutor->Worker->thread
一个运行的线程是作为GC ROOT的。
线程池也会一直保持核心线程数在线程池内,不会被销毁。
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。