线程池系列:
Worker 设计思路
照理说,线程池就是维持着许多线程,然后每个线程都可以很多任务。 但是这里注意一个问题,如果我们创建一个线程时直接传入一个具体的 Runnable,比如
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
}).start();
那么,这个线程执行完打印 hello 这个任务就结束了,根本无法复用线程去执行多个任务。所以,需要不能在创建 Thread 时放入具体的任务,而是要将 Runnable 再封装一次,在它的 run 方法中调用一个获取任务的具体的方法,比如下面这样:
public class Work implements Runnable {
@Override
public void run() {
// runwork 方法才是真正执行任务的方法
runwork();
}
}
main() {
// 创建线程时传入 work,调用逻辑就是 Work#run() -> runwork() -> 具体Runnable的run()
// 所以,只要保证 runwork 方法能一直获取任务,则该线程就能一直运行
// 另外,在 runwork 获取任务时,还可以扩展线程回收策略,因为只要该方法返回了,该线程就该结束了
new Thread(Work).start();
}
理解了我上面说的,ThreadPoolExecutor 的核心逻辑其实就差不多明了了。
Worker 源码分析
线程池中任务执行的最小单元。
ThreadPoolExecutor 的 Worker 比我上面说的做法更加巧妙,它不是以再封装 Runnable 为目的,而是封装 Thread 的同时,又实现了 Runnable 接口,从而达到了线程复用的目的(即 new Thread(this))。
另外,Worker 还保存了创建线程时的第一个任务 firstTask,但是 firstTask 执行完后,就会将它置为 null,然后再通过 getTask() 从任务的队列中不断获取新任务去执行。
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
// 执行当前 worker 的线程
final Thread thread;
// 创建该线程时的任务(第一个任务),执行完后=null
Runnable firstTask;
// 在创建 worker 的时候创建 Thread
Worker(Runnable firstTask) {
// 将AQS的状态设置为-1
// 从后面的isLocked方法可以看到,state!=0 表示已经被加锁
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
// !!!为了线程的复用,Worker本身实现了 Runnable,并且把自己作为任务传递给 thread。非常巧妙的设计!
this.thread = getThreadFactory().newThread(this);
}
// 调用逻辑:Woker#run -> runWorker() -> 具体Runnable的run()
// runWorker 获取任务的方式有二:
// 1.firstTask,执行完就置为 null
// 2.getTask() 不断从从阻塞队列中获取
public void run() {
runWorker(this);
}
}
PS:那要是创建的线程多了,好多线程都没有任务空闲下来了怎么办?
答:若一个线程迟迟等不到任务执行就会被回收,具体回收策略在 getTask() 方法中可以看到
另外,Worker 本身还实现了 AQS,所以其本身也是一个锁,其在执行任务的时候,会锁住自己,任务执行完成之后,会释放自己,保证了在一个线程执行任务时再被丢入别的任务。相关方法如下:
public void lock() { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); // Lock methods
// 尝试加锁,CAS 赋值为 1,表示锁住
protected boolean tryAcquire(int unused) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放锁,释放锁没有 CAS 校验,可以任意的释放锁
protected boolean tryRelease(int unused) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 0 代表没有锁住,否则代表锁住(-1,1)
protected boolean isHeldExclusively() {
return getState() != 0;
}
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}