上一篇说了ThreadPoolExecutor里面的位运算,在后边的源码介绍中就会看到有很多地方调用了那些位运算方法,更加深刻的体会到设计的精妙。
这一篇来搞一下线程池中的Worker
Worker是啥?
Worker是线程池中的工作者,一个Worker绑定了一个线程,同时也是一个可以执行的任务,Worker继承了AbstractQueuedSynchronizer实现了一个不可重入锁。这里贴一张图有助于更好的体会Worker的作用。
image.png
下面是Worker的源码,注释已经写在代码里了。其中的run方法,里面的runWorker(),我们在下一篇,主流程常用方法里面会引出来一起看一下。
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
private static final long serialVersionUID = 6138294804551838833L;
// 执行任务的线程,如果ThreadFactory失败可能为null
final Thread thread;
// 线程执行的任务
Runnable firstTask;
// 每个Worker完成的任务数
volatile long completedTasks;
// 根据给定的任务创建一个Worker
Worker(Runnable firstTask) {
setState(-1); // 设置为-1防止在执行runWorker之前被打断。interruptIfStarted方法只能打断state>=0的
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
runWorker(this);
}
// ============重写AQS的方法START============
// Lock methods
// state=0 代表没有锁 1表示有锁
protected boolean isHeldExclusively() {
return getState() != 0;
}
// 尝试加锁
protected boolean tryAcquire(int unused) {
// status的值更新为1
if (compareAndSetState(0, 1)) {
// 设置当前线程持有锁
setExclusiveOwnerThread(Thread.currentThread());
// 加锁成功
return true;
}
// 加锁失败
return false;
}
// 尝试释放锁
protected boolean tryRelease(int unused) {
// 释放拥有独占访问权的线程
setExclusiveOwnerThread(null);
// state变更为0,释放锁
setState(0);
return true;
}
// ============重写AQS的方法END============
// ============自己定义的方法 START============
public void lock() { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); }
// 中断线程(主要是用于shutdownNow方法)
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
}
// ============自己定义的方法 END============
读完Worker的源码我有一个问题没明白,如果大家有知道的可以评论告诉我一下,互相学习。我也会在工作之余,想尽一切办法解决这个问题。
线程池Worker为什么需要加锁?为什么需要非可重入锁?
网友评论