一个线程在运行结束后, 是不能再次调用start() 方法启动的.
那JDK中的线程池是如何做到线程回收以及复用的呢?
复用原理
复用原理很简单, 就是生产者消费模式
将提交的线程任务写入任务队列, 线程池中的一个线程不断的从任务队列中拿出任务并执行.
BlockingQueueworkQueue = new ArrayBlockingQueue(10);
for(;;){
Runnable r = workQueue.take();
r.run();
}
线程复用
在线程池(ThreadPoolExecutor)中, 线程复用过程也是类似的.
1. 向线程池提交任务之后,
如果当前执行中的线程数是否小于核心线程数(corePoolSize), 则执行addWorker()方法, 直接执行任务;
否则, 将任务添加到任务队列(workQueue)中.
public void execute(Runnable command) {
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
}
if (isRunning(c) && workQueue.offer(command)) {
}
else if (!addWorker(command, false))
reject(command);
}
2. 执行任务时, 首先会创建一个封装了任务和线程信息的Worker对象, 启动并执行worker.
private boolean addWorker(Runnable firstTask, boolean core) {
w = new Worker(firstTask);
final Thread t = w.thread;
t.start();
}
Worker对象封装任务与线程.
private final class Worker extends AbstractQueuedSynchronizer
implements Runnable {
Runnable firstTask;
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
runWorker(this);
}}
3. worker线程启动后, 会执行runWorker()方法,
会根据条件worker.task != null 优先执行提交的任务;
后续执行时, 会根据(task = getTask()), 从任务队列(workQueue)中取出task, 并继续执行.
final void runWorker(Worker w) {Runnable task = w.firstTask;
while (task != null || (task = getTask()) != null) {
task.run();
}
}
4. 从任务队列(workQueue)中取出task
private Runnable getTask() {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
return r;
}
处理流程如下:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有