ThreadPoolExecutor问题定位

本文讲述了如何定位和解决一个由ThreadPoolExecutor引起的内存泄露问题。当使用Executors.newFixedThreadPool创建线程池后,如果没有调用shutdown()方法,会导致线程无法回收,从而引发内存泄露。通过分析源码,揭示了ThreadPoolExecutor的工作原理,并提出了通过shutdown()或allowCoreThreadTimeOut(true)来避免内存资源浪费的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天定位了一个内存泄露的问题,错误如下:

Exception in thread"http-exec-24" java.lang.OutOfMemoryError: unable to create newnative thread

众所周知,内存泄露和内存溢出JVM都会抛出OutOfMemoryError异常。内存泄露是由于程序编码有缺陷,通过修改Java代码可以修复。内存溢出则是由于JVM运行时需要占用的内存大于JVM启动参数所设置的。

 

看下现有代码:

/***

 *  测试线程池关闭。

 * @authorjim

 *

 */

public class ThreadPoolTest {

 

       /**

        * 启动线程池,运行任务。

        */

       public static voidpoolExecute(){

             

              int size =10;

              ExecutorService executor =Executors.newFixedThreadPool(size);

             

              for (int i = 0;i < size; i ++){

                     executor.execute(newRunnable() {

                            @Override

                            publicvoid run(){

                            }

                     });

              }

       }

      

       public static voidmain(String[] args){

              poolExecute();

              try {

                    

                     // 主线程挂起

                     CountDownLatch latch = newCountDownLatch(1);

                     latch.await();

              } catch(InterruptedException e) {

              }

       }

}

 

一眼看去貌似没有问题,poolExecute返回后,executor对象也应该销毁了。

用jconsole连接到程序,发现由ExecutorService启动的线程并未关闭,多次调用poolExecute后就会导致残留太多的线程。

 

查看Executors.newFixedThreadPool方法如下:

public static ExecutorService newFixedThreadPool(intnThreads) {

        return newThreadPoolExecutor(nThreads, nThreads,

                                      0L,TimeUnit.MILLISECONDS,

                                      newLinkedBlockingQueue<Runnable>());

}

其返回了一个ThreadPoolExecutor对象。

查看ThreadPoolExecutor的实现,发现线程启动后会循环从Worker队列中取出Worker执行,而Worker队列采用的是LinkedBlockingQueue,当队列中没有要执行的Worker线程会等待,即线程无法结束,导致线程无法回收。若要结束线程,需要调用ThreadPoolExecutor.shutdown()方法,停止线程。

还有一种方法可以通过调用ThreadPoolExecutor. allowCoreThreadTimeOut(true)允许超时自动关闭。

更多ThreadPoolExecutor的介绍请参考Java API。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值