java
ExecutorService pool = new ThreadPoolExecutor(2, 4, 6,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
以上创建了一个 ThreadPoolExecutor 线程池对象,它是Java 并发编程中最核心的类之一。
其中的参数解读如下:
1. 核心与最大任务处理能力
corePoolSize = 2:核心线程数。这是线程池的"常驻员工",即便没活干,这 2 个人也会留着。maximumPoolSize = 4:最大线程数。如果活太多(队列满了),线程池会临时扩招,最多招到 4 个人。
2. 空闲处理机制
keepAliveTime = 6,unit = TimeUnit.SECONDS:如果非核心线程(那 2 个扩招的临时工)在 6 秒内没有接到新任务,就会被裁掉,以节省资源。
3. 工作排队区域
new ArrayBlockingQueue<>(2):任务缓存区。如果核心的 2 个人都在忙,排好队的新任务会放在队列里等。这个队列最多放 2 个任务。
4. 线程创建工厂
Executors.defaultThreadFactory():这就是一个"招聘负责人",负责给线程取名字、设置优先级等,用的是默认的招聘标准。
5. 拒绝策略(最关键的部分)
new ThreadPoolExecutor.AbortPolicy():这是默认的拒绝策略 。- 含义 :如果 4 个人都在忙,且队列里的 2 个位子也满了,再有新任务进来,线程池会直接抛出
RejectedExecutionException异常,不再处理这个新任务。
- 含义 :如果 4 个人都在忙,且队列里的 2 个位子也满了,再有新任务进来,线程池会直接抛出
一句话总结流程(工作逻辑)
当任务来临时,它是这样被处理的:
- 先找常驻员工(核心 2 人):能处理就处理。
- 常驻员工满了,去排队:如果队列没满(还能放 2 个),就在那里等着。
- 队列满了,找临时工:去扩招临时工,直到总人数达到 4 人。
- 都满了,拒绝任务 :如果 4 个人都在忙,队列也没位子了,触发
AbortPolicy,直接抛出异常,拒绝接受新任务。
为什么这样做?
这种设计是为了资源保护。如果不设置这些限制(比如队列无限大、线程无限多),在高并发下,程序可能会因为创建过多的线程导致内存溢出(OOM),或者因为大量的等待任务拖垮整个系统。
形象比喻:
这就像一个只有 2 个固定柜台的银行,大厅里有 2 把椅子(队列)。
- 最多一共开 4 个窗口(最大线程数)。
- 如果有人进门,先去柜台;柜台满了,去椅子上坐着等;椅子也坐满了,再开临时窗口。
- 如果临时窗口也满了,大厅也站不下了,经理只能对着进门的第 7 个人喊:"抱歉,今天不办了,请回吧!"(这就是
AbortPolicy)。
这段代码适合在对系统实时性要求较高、且不允许任务无限制堆积的场景下使用。