请用 Java 手写实现一个线程池,描述其核心组件与工作流程。
考察说明
考查对线程池原理和并发编程的理解,以及手写实现能力。
回答思路
- 【回答框架 1】线程池核心组件包括工作线程集合、任务队列、拒绝策略和线程工厂。核心参数有核心线程数、最大线程数、空闲存活时间及任务队列。
- 【回答框架 2】核心流程:提交任务时,若工作线程数小于核心线程数则创建新线程执行;否则尝试加入任务队列,队列满且未达最大线程数则创建非核心线程,达到最大线程数则执行拒绝策略。
- 【回答框架 3】手写实现要点:用线程安全队列如 BlockingQueue 保存任务,用 Set 或 List 管理 Worker 线程,Worker 循环从队列取任务执行。
- 【回答框架 4】需要处理 shutdown 和 shutdownNow,管理线程状态,并注意并发控制如锁和原子变量。
- 【回答框架 5】需实现拒绝策略接口,常见有 AbortPolicy、CallerRunsPolicy 等,并保证任务提交与执行的一致性和线程安全。
- 【关键点 1】核心参数包括 corePoolSize、maximumPoolSize、keepAliveTime、workQueue 和 RejectedExecutionHandler。
- 【关键点 2】执行流程遵循 ThreadPoolExecutor 的通用逻辑:先核心线程,再队列,再最大线程,最后拒绝。
- 【关键点 3】Worker 线程循环从队列获取任务,空闲超时后回收非核心线程。
- 【关键点 4】shutdown 停止接受新任务,继续处理队列中任务;shutdownNow 中断所有线程并返回待处理任务。
- 【关键点 5】手写时需要保证并发安全,使用锁或并发容器,并正确处理中断和异常。
- 【易错点 1】直接将线程池的互斥机制等同于业务幂等,实际需结合唯一标识等去重。
- 【易错点 2】忽略线程安全或中断处理,导致任务丢失或线程泄漏。
- 【易错点 3】对线程数计算使用固定公式 Ncpu×(1+W/C),未结合实际压测调整,实际应以资源上限和延迟目标为准。