线程池异常问题排查

问题复现

如果线程池设置的不合适会出现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查看任务线程状态。
线程池异常问题排查_第1张图片
可以看到线程是WAITING状态,可是我们的任务还有1个没有被执行。

解决方案

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

你可能感兴趣的:(问题排查,java,jvm)