
1. 为什么需要从零实现线程池第一次接触线程池这个概念是在处理一个批量图片压缩的需求时。当时我简单粗暴地为每张图片创建了一个独立线程结果当同时处理上千张图片时程序直接崩溃——线程创建和销毁的开销远超实际处理时间。这个惨痛教训让我意识到线程池不是可选项而是高并发编程的必需品。线程池的核心价值在于对线程生命周期的统一管理。想象一个快递站如果每次有包裹到达都临时雇佣快递员创建线程送完就解雇销毁线程光是人员调度就会耗尽所有资源。而线程池就像常驻的快递团队任务包裹来了直接分配给空闲员工线程完事后员工继续等待新任务避免了重复招聘-培训-解雇的开销。Java标准库提供的ThreadPoolExecutor虽然功能完善但直接使用它就像开自动挡赛车——方便但难以真正理解传动原理。通过从零实现我们能够透彻掌握线程调度、任务队列、拒绝策略等核心机制根据特定场景定制优化策略如IO密集型与CPU密集型的不同处理为后续阅读源码打下坚实基础JDK线程池代码量约2000行理解自制简化版后再看会轻松很多2. 线程池核心架构设计2.1 线程池三要素一个基础线程池需要三个核心组件协同工作任务队列BlockingQueue存放待执行任务生产者线程提交任务到队列工作线程从队列获取任务。这个缓冲层解耦了任务提交与执行。工作线程组Worker Threads常驻线程不断从队列获取任务并执行。线程数量需要根据硬件核心数和任务类型动态调整。管理组件Pool Manager控制线程生命周期、处理任务拒绝、监控运行状态。这是最复杂的部分需要处理各种边界条件。2.2 状态机设计参考ThreadPoolExecutor我们定义五种状态private static final int RUNNING 0; // 接收新任务并处理队列任务 private static final int SHUTDOWN 1; // 不接收新任务但处理队列任务 private static final int STOP 2; // 不接收新任务不处理队列任务 private static final int TIDYING 3; // 所有任务终止workerCount0 private static final int TERMINATED 4; // terminated()方法已完成状态转换需要原子操作保证线程安全。例如调用shutdown()时if (compareAndSetState(RUNNING, SHUTDOWN)) { interruptIdleWorkers(); // 中断空闲线程 onShutdown(); // 钩子方法 }2.3 关键参数设计corePoolSize核心线程数即使空闲也不会被回收maximumPoolSize线程池最大容量keepAliveTime非核心线程空闲存活时间workQueue任务阻塞队列ArrayBlockingQueue/LinkedBlockingQueuethreadFactory线程创建工厂可定制线程名、优先级等handler拒绝策略AbortPolicy/CallerRunsPolicy等注意参数间存在约束关系。比如当corePoolSize0时需要设置合理的keepAliveTime否则线程会立即被回收。3. Worker线程实现细节3.1 Worker类设计每个Worker对应一个工作线程封装了线程和任务执行逻辑private final class Worker extends AbstractQueuedSynchronizer implements Runnable { final Thread thread; // 实际执行线程 Runnable firstTask; // 初始任务可能为null Worker(Runnable firstTask) { this.firstTask firstTask; this.thread getThreadFactory().newThread(this); } public void run() { runWorker(this); // 核心执行逻辑 } // 省略锁方法... }使用AQS实现简单锁防止任务执行期间被中断。这种设计比直接使用synchronized更灵活。3.2 任务执行流程final void runWorker(Worker w) { Thread wt Thread.currentThread(); Runnable task w.firstTask; w.firstTask null; w.unlock(); // 允许中断 boolean completedAbruptly true; try { while (task ! null || (task getTask()) ! null) { w.lock(); // 如果线程池正在停止确保线程被中断 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() runStateAtLeast(ctl.get(), STOP))) !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); // 前置钩子 try { task.run(); afterExecute(task, null); // 后置钩子 } catch (Throwable ex) { afterExecute(task, ex); // 异常处理 throw ex; } } finally { task null; w.completedTasks; w.unlock(); } } completedAbruptly false; } finally { processWorkerExit(w, completedAbruptly); } }3.3 任务获取逻辑private Runnable getTask() { boolean timedOut false; // 上次poll是否超时 for (;;) { int c ctl.get(); int rs runStateOf(c); // 检查队列是否为空 if (rs SHUTDOWN (rs STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc workerCountOf(c); // 是否允许回收线程核心线程例外 boolean timed allowCoreThreadTimeOut || wc corePoolSize; if ((wc maximumPoolSize || (timed timedOut)) (wc 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { Runnable r timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r ! null) return r; timedOut true; } catch (InterruptedException retry) { timedOut false; } } }4. 关键问题与优化策略4.1 线程池大小动态调整理想线程数取决于任务类型CPU密集型N_cpu 1避免上下文切换开销IO密集型N_cpu * (1 WT/ST)WT等待时间ST服务时间实现动态调整接口public void setCorePoolSize(int corePoolSize) { if (corePoolSize 0) throw new IllegalArgumentException(); int delta corePoolSize - this.corePoolSize; this.corePoolSize corePoolSize; if (workerCountOf(ctl.get()) corePoolSize) interruptIdleWorkers(); else if (delta 0) { int k Math.min(delta, workQueue.size()); while (k-- 0 addWorker(null, true)) { if (workQueue.isEmpty()) break; } } }4.2 优雅关闭策略实现分阶段关闭public void shutdown() { final ReentrantLock mainLock this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(SHUTDOWN); interruptIdleWorkers(); onShutdown(); // 钩子方法 } finally { mainLock.unlock(); } tryTerminate(); } public ListRunnable shutdownNow() { ListRunnable tasks; final ReentrantLock mainLock this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(STOP); interruptWorkers(); tasks drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }4.3 拒绝策略实现四种常用策略示例// 直接抛出异常 public static class AbortPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException(Task r.toString() rejected from e.toString()); } } // 调用者线程直接运行 public static class CallerRunsPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } } // 丢弃最老任务 public static class DiscardOldestPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } } // 静默丢弃 public static class DiscardPolicy implements RejectedExecutionHandler { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }5. 性能优化实战技巧5.1 上下文切换优化通过线程绑定减少缓存失效// 为每个线程维护独立的任务队列 private final ListBlockingQueueRunnable workerQueues; // 任务路由策略 public void execute(Runnable command) { if (command null) throw new NullPointerException(); int index ThreadLocalRandom.current().nextInt(workerQueues.size()); if (!workerQueues.get(index).offer(command)) { // 处理拒绝策略 } }5.2 监控接口实现添加监控指标public class MonitorStats { private final int poolSize; private final int activeCount; private final long completedTaskCount; private final int queueSize; // getter方法... } public MonitorStats getMonitorStats() { final ReentrantLock mainLock this.mainLock; mainLock.lock(); try { return new MonitorStats( workerCountOf(ctl.get()), workers.stream().filter(Worker::isLocked).count(), completedTaskCount, workQueue.size() ); } finally { mainLock.unlock(); } }5.3 异常处理增强全局异常捕获protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); if (t null r instanceof Future?) { try { Future? future (Future?) r; if (future.isDone()) future.get(); } catch (CancellationException ce) { t ce; } catch (ExecutionException ee) { t ee.getCause(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } if (t ! null) { // 记录到日志系统 log.error(Uncaught exception in thread pool, t); // 可选重启工作线程 if (!addWorker(null, false)) reject(r); } }6. 测试验证方案6.1 功能测试用例Test public void testBasicOperation() throws InterruptedException { ThreadPoolExecutor executor new MyThreadPoolExecutor( 2, 4, 30, TimeUnit.SECONDS, new ArrayBlockingQueue(10)); AtomicInteger counter new AtomicInteger(); // 提交100个任务 for (int i 0; i 100; i) { executor.execute(() - { counter.incrementAndGet(); try { Thread.sleep(10); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } executor.shutdown(); executor.awaitTermination(1, TimeUnit.MINUTES); assertEquals(100, counter.get()); } Test(expected RejectedExecutionException.class) public void testRejectionPolicy() { ThreadPoolExecutor executor new MyThreadPoolExecutor( 1, 1, 0, TimeUnit.SECONDS, new SynchronousQueue(), new AbortPolicy()); // 第一个任务占用唯一线程 executor.execute(() - { try { Thread.sleep(1000); } catch (InterruptedException ignored) {} }); // 第二个任务应该被拒绝 executor.execute(() - {}); }6.2 性能压测对比使用JMH进行基准测试BenchmarkMode(Mode.Throughput) OutputTimeUnit(TimeUnit.SECONDS) public class ThreadPoolBenchmark { Benchmark public void testJDKThreadPool(Blackhole bh) { ExecutorService executor Executors.newFixedThreadPool(4); for (int i 0; i 1000; i) { executor.submit(() - bh.consume(doWork())); } executor.shutdown(); } Benchmark public void testCustomThreadPool(Blackhole bh) { MyThreadPoolExecutor executor new MyThreadPoolExecutor( 4, 4, 0, TimeUnit.SECONDS, new LinkedBlockingQueue()); for (int i 0; i 1000; i) { executor.execute(() - bh.consume(doWork())); } executor.shutdown(); } private double doWork() { return Math.sin(Math.random()) Math.cos(Math.random()); } }6.3 死锁检测方案通过线程转储分析public void checkDeadlock() { ThreadMXBean threadMXBean ManagementFactory.getThreadMXBean(); long[] threadIds threadMXBean.findDeadlockedThreads(); if (threadIds ! null) { ThreadInfo[] threadInfos threadMXBean.getThreadInfo(threadIds); for (ThreadInfo threadInfo : threadInfos) { System.err.println(Deadlock detected:); System.err.println(threadInfo); } // 应急处理创建新线程池转移任务 emergencyRestart(); } }7. 生产环境注意事项线程泄漏检测实现线程回收监控private void processWorkerExit(Worker w, boolean completedAbruptly) { if (completedAbruptly) decrementWorkerCount(); final ReentrantLock mainLock this.mainLock; mainLock.lock(); try { completedTaskCount w.completedTasks; workers.remove(w); // 记录异常退出 if (completedAbruptly) { abnormalExitCount.incrementAndGet(); if (abnormalExitCount.get() threshold) { alert(Too many worker threads exiting abnormally); } } } finally { mainLock.unlock(); } tryTerminate(); }动态参数调优基于监控数据自动调整public void autoTune() { MonitorStats stats getMonitorStats(); double utilization (double)stats.getActiveCount() / stats.getPoolSize(); if (utilization 0.8 stats.getPoolSize() maximumPoolSize) { setCorePoolSize(Math.min( corePoolSize 2, maximumPoolSize )); } else if (utilization 0.2) { setCorePoolSize(Math.max( corePoolSize - 1, 1 )); } }任务级监控跟踪单个任务生命周期public class TrackableTask implements Runnable { private final Runnable actualTask; private final long submitTime; private volatile long startTime; private volatile long finishTime; Override public void run() { startTime System.currentTimeMillis(); try { actualTask.run(); } finally { finishTime System.currentTimeMillis(); log.info(Task execution time: {}ms, finishTime - startTime); } } }实现线程池的过程中最深的体会是魔鬼藏在细节里。比如最初我认为worker线程的interrupt处理很简单直到实际测试时才发现各种边界条件——线程可能在getTask()阻塞可能在task.run()执行中也可能刚好在两个阶段之间。这些实战中的坑促使我添加了更完善的状态检查机制。