newFixedThreadPool使用不当导致线程爆炸

目录

1、问题

2、问题排查

2.1用newFixedThreadPool

2.2用ThreadPoolExecutor

3、总结


1、问题

某个项目,需要异步跑任务。用户创建了5个任务,然后服务器出现假死,看服务器日志,发现线程爆发式增加导致服务假死。

2、问题排查

发现跑任务的代码,用了newFixedThreadPool,而且没有释放

代码结构大致如下:

public void test() throws InterruptedException {
    for (int p = 0; p < 12; p++) {
        ExecutorService executorService = Executors.newFixedThreadPool(90);
        //做一些逻辑
        CompletableFuture.runAsync(() -> {
            //todo 做一些逻辑
            ExecutorService executorService2 = Executors.newFixedThreadPool(50);
            //做一些逻辑
            CompletableFuture.runAsync(()-> {
                //todo 做一些逻辑2
            },executorService2);
        }, executorService);
    }
}

排查的时候就觉得newFixedThreadPool不会主动释放线程,线程会无限膨胀。

写个例子验证问题

2.1用newFixedThreadPool

public static void main(String[] args) throws InterruptedException {
    testFixThread();
    //打断点
    System.out.println("开始查看总线程--");
    Thread.sleep(5000);
}



public static void testFixThread(){
    for(int p=0;p<3;p++){
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        // 执行结果
        List<CompletableFuture<Void>> resultList = Lists.newArrayList();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
                System.out.println("线程1:,"+Thread.currentThread().getName()+","+finalI);
            },executorService);
            resultList.add(completableFuture);
        }
        resultList.forEach(CompletableFuture::join);
       // executorService.shutdown();
        List<CompletableFuture<Void>> resultList1 = Lists.newArrayList();
        ExecutorService executorService2 = Executors.newFixedThreadPool(6);
        for (int i = 0; i < 7; i++) {
            int finalI = i;
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
                System.out.println("线程2:,"+Thread.currentThread().getName()+","+finalI);
            },executorService2);
            resultList1.add(completableFuture);
        }
        resultList1.forEach(CompletableFuture::join);
       // executorService2.shutdown();
    }
}

(1)不主动释放线程池,执行到开始查看总线程,发现还有33个线程没有释放
(2)主动释放线程池,线程正常释放

2.2用ThreadPoolExecutor

public static void main(String[] args) throws InterruptedException {
    testTheadExcetor();
    System.out.println("开始查看总线程--");
    Thread.sleep(5000);
}

public static void testTheadExcetor(){
    for(int p=0;p<3;p++){
        ExecutorService executorService = new ThreadPoolExecutor(2, 5, 60L,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new ThreadPoolExecutor.CallerRunsPolicy());
        // 执行结果
        List<CompletableFuture<Void>> resultList = Lists.newArrayList();
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
                System.out.println("线程1:,"+Thread.currentThread().getName()+","+finalI);
            },executorService);
            resultList.add(completableFuture);
        }
        resultList.forEach(CompletableFuture::join);
       // executorService.shutdown();
        List<CompletableFuture<Void>> resultList1 = Lists.newArrayList();
        ExecutorService executorService2 = new ThreadPoolExecutor(2, 6, 60L,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 7; i++) {
            int finalI = i;
            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
                System.out.println("线程2:,"+Thread.currentThread().getName()+","+finalI);
            },executorService2);
            resultList1.add(completableFuture);
        }
        resultList1.forEach(CompletableFuture::join);
       // executorService2.shutdown();
    }
}

发现有15个核心线程没有释放

3、总结

(1)newFixedThreadPool不会主动释放线程,ThreadPoolExecutor会保留核心线程

(2)用newFixedThreadPool要主动释放线程,免得引起线程膨胀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值