核心线程和非核心线程的核心区别在于存活策略:核心线程默认永久驻留,而非核心线程在空闲时会按超时机制回收。具体做法是配置 threadpoolexecutor 时区分 corepoolsize 和 maximumpoolsize,任务先入队,队列满后才会创建非核心线程。

线程池如何决定创建哪种线程
线程池通过 execute() 方法按固定顺序判断是否需要创建新线程。首先检查核心线程数是否已满,未满则创建核心线程;若已满,尝试将任务加入工作队列;若队列也满了,且当前总线程数未达上限,则创建非核心线程;否则执行拒绝策略。

import java.util.concurrent.*;
public class ThreadDemo {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2)
);
for (int i = 0; i < 7; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " running on " + Thread.currentThread().getName());
try { Thread.sleep(1000); } catch (InterruptedException e) {}
});
}
executor.shutdown();
}
}
非核心线程的回收时机是什么
非核心线程在完成任务后,如果空闲时间超过 keepAliveTime 参数设定的值,就会被终止并从线程池中移除。这一机制确保了在高并发结束后,线程池能自动释放资源,只保留核心的少量线程以应对突发流量。
立即学习“Java免费学习笔记(深入)”;

import java.util.concurrent.*;
public class KeepAliveDemo {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
1, // corePoolSize
3, // maximumPoolSize
2L, TimeUnit.SECONDS, // keepAliveTime
new ArrayBlockingQueue<>(1)
);
// 触发创建非核心线程
executor.submit(() -> {});
executor.submit(() -> {});
executor.submit(() -> {});
// 等待非核心线程因空闲被回收
Thread.sleep(3000);
System.out.println("Active count: " + executor.getActiveCount());
System.out.println("Pool size: " + executor.getPoolSize());
executor.shutdown();
}
}
当队列满且线程数已达上限时会发生什么
当核心线程全部忙碌、工作队列也达到容量上限,且当前线程总数等于 maximumPoolSize 时,新提交的任务将无法被处理,线程池会触发拒绝策略(RejectedExecutionHandler)。默认情况下,这会抛出 RejectedExecutionException 异常,开发者需根据业务需求自定义处理逻辑,如记录日志或丢弃任务。


















