线程池异常问题排查

问题复现

如果线程池设置的不合适会出现ask xxx rejected from java.util.concurrent的现象
下面通过代码还原一下:

@Slf4j
public class ThreadRejectedTest {
    public static Random random = new Random();

    public static void main(String[] args) throws Exception {

        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-pool-%d").build();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 5L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(2),
                threadFactory,
                new ThreadPoolExecutor.AbortPolicy());

        long start = System.currentTimeMillis();
        ThreadRejectedTest threadTest = new ThreadRejectedTest();
        // 线程池1
        CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
            return threadTest.doTaskOne("1");
        }, executor);
        CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
            return threadTest.doTaskOne("2");
        }, executor);
        CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> {
            return threadTest.doTaskOne("3");
        }, executor);
        CompletableFuture<String> task4 = CompletableFuture.supplyAsync(() -> {
            return threadTest.doTaskOne("4");
        }, executor);
        CompletableFuture<String> task5 = CompletableFuture.supplyAsync(() -> {
            return threadTest.doTaskOne("5");
        }, executor);

        // 一起执行
        CompletableFuture.allOf(task1, task2, task3, task4, task5).join();

        long end = System.currentTimeMillis();

        log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
    }

    public String doTaskOne(String taskNo) {
        log.info("开始任务:{}", taskNo);
        long start = System.currentTimeMillis();
        try {
            Thread.sleep(random.nextInt(10000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        log.info("完成任务:{},耗时:{} 毫秒", taskNo, end - start);
        return "任务完成";
    }

}

执行后会出现下面的异常:

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.CompletableFuture$AsyncSupply@d8355a8 rejected from java.util.concurrent.ThreadPoolExecutor@59fa1d9b[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]
	at com.freemarker.demo.jvm.ThreadRejectedTest$MyRejectedExecutionHandler.rejectedExecution(ThreadRejectedTest.java:81)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at java.util.concurrent.CompletableFuture.asyncSupplyStage(CompletableFuture.java:1604)
	at java.util.concurrent.CompletableFuture.supplyAsync(CompletableFuture.java:1830)
	at com.freemarker.demo.jvm.ThreadRejectedTest.main(ThreadRejectedTest.java:48)

问题分析

可以用dump获取堆快照,导入到visualVm查看任务线程状态。
在这里插入图片描述
可以看到线程是WAITING状态,可是我们的任务还有1个没有被执行。

解决方案

出现此问题,我们需要从几个方面考虑:
1.首先看是不是提交给线程池的任务数据太多了
2.是不是业务代码里在大量的创建对象
3.线程池拒绝策略设置不合理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值