线程池的设计思路,你真的了解么?


当有线程提交时,创建线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}

如果线程小于核心线程数则创建新的线程addWorker,借助于阻塞队列workQueue的功能,将任务放到队列里,线程运行时会从getTask方法中获取任务并执行。在上面的代码中也可以看出当阻塞队列放不下了也会去创建新的线程,因为workQueue.offer(command)false

如何维护核心线程,超过核心线程数量的线程具体是什么时候销毁的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?

for (;;) {
int c = ctl.get();
int rs = runStateOf(c);

// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}

int wc = workerCountOf(c);

// Are workers subject to culling?
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;
}
}
}

首先明确一下,这个getTask方法是各个线程获取任务调用的方法。我们都知道正常结束的线程会自动销毁,那么如果我不想让线程销毁,让线程池一直维护核心数目的线程要怎么做呢?设计者还是借助了阻塞队列的能力,如果线程数目小于等于核心线程数那么这个线程会受到workQueue.take方法而阻塞,这样线程不就不会结束了么,当有新的任务放到阻塞队列里,take方法就会立马返回,这样线程就可以持续下去一直不被销毁,这也就是线程池维护核心线程数目的原理。


还有一种情况,如果线程数超过核心线程数呢?回想一下,ThreadPoolExecutor构造器中是不是有一个keepAliveTime参数,当创建的线程超过核心线程数后,超过的线程不会立即销毁,会等待一段时间,这个时间就是keepAliveTime,实现原理还是借助于阻塞队列,这次用的是它的poll方法,polltake的区别就是poll不会一直阻塞,如果超过设置的时间还没有拿到任务则直接返回,这样就达到了释放线程的目的,线程也就被销毁了。


本文作者:oldmee
本文链接:https://oldmee.github.io/2023/06/01/thread-pool-executor/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。