请说明 Java 线程池的工作原理。
考察说明
考查对 Java 线程池核心机制的理解,包括任务提交、线程复用、队列与拒绝策略。
回答思路
- 【回答框架 1】线程池通过核心线程数、最大线程数、工作队列和拒绝策略管理任务执行。提交任务时,若运行线程数小于核心线程数则创建新线程;否则尝试入队,队列满且未达最大线程数时创建非核心线程,超过最大线程数则触发拒绝策略。
- 【回答框架 2】核心线程默认不回收,非核心线程在空闲超时后回收。任务队列通常使用阻塞队列,如 ArrayBlockingQueue 或 LinkedBlockingQueue,线程从队列取任务执行,实现线程复用,减少创建销毁开销。
- 【回答框架 3】拒绝策略有 AbortPolicy 抛异常、CallerRunsPolicy 由提交线程执行、DiscardPolicy 静默丢弃、DiscardOldestPolicy 丢弃队首任务。不同策略适合不同场景,需按业务可靠性要求选择。
- 【回答框架 4】线程池大小需结合任务类型估算,CPU 密集可用 Ncpu+1,IO 密集可用 Ncpu*(1+W/C),但最终需通过压测和资源上限确定,避免固定公式误用。
- 【回答框架 5】常见风险包括线程池耗尽导致任务拒绝、队列过长造成内存压力、核心线程数设置过大浪费资源。可通过监控队列深度和活跃线程数及时调整参数。
- 【关键点 1】线程池核心参数包括核心线程数、最大线程数、工作队列和拒绝策略。
- 【关键点 2】任务提交顺序是先创建核心线程,再入队,再创建非核心线程,最后拒绝。
- 【关键点 3】核心线程通常不回收,非核心线程在空闲超时后回收。
- 【关键点 4】拒绝策略默认 AbortPolicy 抛出 RejectedExecutionException,可选用 CallerRunsPolicy 等。
- 【关键点 5】线程池大小需依据任务类型和压测调整,固定公式仅作初始估算。
- 【易错点 1】将线程池大小公式当作精确值,忽略实际资源限制和延迟目标。
- 【易错点 2】认为核心线程一定不回收,实际可通过 allowCoreThreadTimeOut 设置回收。
- 【易错点 3】忽略任务队列容量导致的 OOM 或拒绝风险,未结合监控调整参数。