问题复现
如果线程池设置的不合适会出现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.线程池拒绝策略设置不合理。