核心线程数为3的线程池提交2个任务就被拒绝?
2022-06-09
阅读量
话不多说,先看代码
public static void main(String[] args) throws Exception {
// 创建线程池,核心线程和最大线程数都为3,任务队列大小为1
ThreadPoolExecutor taskPoolExecutor = new ThreadPoolExecutor(3, 3, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
// 预先初始化3个核心线程
taskPoolExecutor.prestartAllCoreThreads();
// 提交2个任务,异常:RejectedExecutionException,理论上有可能不出现异常,但实际运行时,基本上是必现的
for (int i = 0; i < 2; i++) {
final int finalI = i;
taskPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " : " + finalI);
});
}
}
示例代码中,创建了核心线程和最大线程数都为3,任务队列大小为1的线程池,但只提交了2个任务,就抛出了RejectedExecutionException异常,结果有些出乎意料。
但分析了线程池的执行过程后,一切又都是合情合理的。
新的线程池,核心线程初始化后,活动线程数等于核心线程数,新的任务直接进入阻塞队列,因为阻塞队列的大小只有1,第一个任务还没被任务线程取出处理时,第二个任务尝试入队失败,而活动线程数等于最大线程数,不能再创建新的线程处理任务,执行默认拒绝策略,抛出异常。
总结
当前活动线程数大于等于最大线程数时,即使这些活动线程当前是空闲状态,新加入的任务(未被活动线程及时取出处理)超出队列大小限制,线程池即执行拒绝策略
当前线程数 < 核心线程数
提交任务时,创建新的线程处理这个任务
当前线程数 >= 核心线程数
提交任务时,尝试把任务加入阻塞队列,加入成功结束,等待活动线程从队列中取出任务处理
当前线程数 >= 核心线程数 && 加入阻塞队列失败 && 当前线程数 < 最大线程数
提交任务时,创建新的线程处理这个任务
当前线程数 >= 核心线程数 && 加入阻塞队列失败 && 当前线程数 >= 最大线程数
提交任务时,执行拒绝策略