【并发专题】线程池ThreadPoolExecutorl底层原理源码分析
发布人:shili8
发布时间:2025-03-04 11:24
阅读次数:0
**并发专题: 线程池ThreadPoolExecutor底层原理源码分析**
在Java世界中,线程池是实现高性能并发编程的关键组件之一。ThreadPoolExecutor是Java.util.concurrent包中的一个重要类,它提供了一个线程池来管理和执行任务。下面我们将深入探讨ThreadPoolExecutor的底层原理和源码分析。
**一、线程池的基本概念**
线程池是一种资源共享机制,允许多个线程共用同一个线程对象。线程池通过维护一个线程集合来实现这一点,每当有任务需要执行时,就从线程集合中取出一个可用的线程来执行该任务。
**二、ThreadPoolExecutor的构造**
ThreadPoolExecutor的构造函数如下所示:
javapublic ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), (RejectedExecutionHandler) new ThreadPoolExecutor.AbortPolicy()); }
从构造函数中可以看出,ThreadPoolExecutor需要以下参数:
* `corePoolSize`:线程池的核心大小,即线程集合中的线程数量。
* `maximumPoolSize`:线程池的最大大小,即线程集合中的线程数量上限。
* `keepAliveTime`:线程集合中线程的存活时间,单位为`unit`指定的时间单位。
* `workQueue`:任务队列,用于存放等待执行的任务。
* `threadFactory`:线程工厂,用于创建新线程。
* `rejectedExecutionHandler`:拒绝策略,用于处理无法添加到线程集合中的任务。
**三、线程池的工作流程**
下面是线程池的工作流程:
1. **任务提交**:当有任务需要执行时,首先会尝试将该任务添加到线程集合中。如果线程集合中有可用的线程,则会从线程集合中取出一个线程来执行该任务。
2. **线程创建**:如果线程集合中没有可用的线程,则会创建新线程并添加到线程集合中。
3. **任务执行**:当线程集合中有可用的线程时,会从线程集合中取出一个线程来执行该任务。
4. **任务完成**:当任务执行完毕后,线程将返回线程集合中等待下一次任务的状态。
**四、源码分析**
下面是ThreadPoolExecutor的关键方法源码分析:
### `execute(Runnable command)`
javapublic void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, c)) return; c = ctl.get(); } if (isRunning(c) && workerCountOf(c) < maximumPoolSize && !surplusPredicates().anyMatch(surplus -> surplus.test(command))) { int reints = enlargedPoolSize(c); if (workerCountOf(c) >= reints) addWorker(command, c); else if (ctl.compareAndSet(c, c, c | WORKER_START)) workerStart(command); } else if (!surplusPredicates().anyMatch(surplus -> surplus.test(command))) { rejectedExecution(command, this); } }
从源码中可以看出,`execute(Runnable command)`方法首先会尝试将任务添加到线程集合中。如果线程集合中有可用的线程,则会从线程集合中取出一个线程来执行该任务。
### `addWorker(Runnable firstTask, boolean core)
`javaprivate boolean addWorker(Runnable firstTask, boolean core) { Thread t; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { int c = ctl.get(); if (workerCountOf(c) ==0) t = getNewThread(core); else { t = addWorkerWaiter(firstTask, core); } } finally { mainLock.unlock(); } if (t == null) return false; Workers.wakeOne(); Thread.startThread(t); if (afterExecute(t, null)) return true; return false; }
从源码中可以看出,`addWorker(Runnable firstTask, boolean core)`方法首先会尝试创建新线程。如果线程集合中有可用的线程,则会从线程集合中取出一个线程来执行该任务。
### `workerStart(Runnable task)`
javaprivate void workerStart(Runnable task) { Thread t = currentThread(); if (t.isAlive()) throw new Error("task != null, thread.holdsLock(this)"); int c = ctl.get(); if (!isRunning(c)) { Worker w; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { if (workerCountOf(c) ==0) t = getNewThread(false); else t = addWorkerWaiter(task, false); } finally { mainLock.unlock(); } if (t == null) return; } Worker w = new Worker(this, task); Thread.startThread(w); }
从源码中可以看出,`workerStart(Runnable task)`方法首先会尝试创建新线程。如果线程集合中有可用的线程,则会从线程集合中取出一个线程来执行该任务。
**五、总结**
本文深入探讨了ThreadPoolExecutor的底层原理和源码分析。通过对关键方法的源码分析,可以看出,ThreadPoolExecutor的工作流程主要包括任务提交、线程创建、任务执行和任务完成四个步骤。在这些步骤中,ThreadPoolExecutor会尝试将任务添加到线程集合中,如果线程集合中有可用的线程,则会从线程集合中取出一个线程来执行该任务。如果线程集合中没有可用的线程,则会创建新线程并添加到线程集合中。