一直用并发库,但ThreadPoolExecutor的源码没有详细看过,主要想看看Doug Lea大神的设计思路。
说一下在一处代码上的疑问,主要是Worker这个类,内部有一处代码
private final ReentrantLock runLock = new ReentrantLock();
有2处方法会用到
第一个是runTask方法
private void runTask(Runnable task) {
final ReentrantLock runLock = this.runLock;
runLock.lock();
try {
/*
* Ensure that unless pool is stopping, this thread
* does not have its interrupt set. This requires a
* double-check of state in case the interrupt was
* cleared concurrently with a shutdownNow -- if so,
* the interrupt is re-enabled.
*/
if (runState < STOP &&
Thread.interrupted() &&
runState >= STOP)
thread.interrupt();
/*
* Track execution state to ensure that afterExecute
* is called only if task completed or threw
* exception. Otherwise, the caught runtime exception
* will have been thrown by afterExecute itself, in
* which case we don't want to call it again.
*/
boolean ran = false;
beforeExecute(thread, task);
try {
task.run();
ran = true;
afterExecute(task, null);
++completedTasks;
} catch (RuntimeException ex) {
if (!ran)
afterExecute(task, ex);
throw ex;
}
} finally {
runLock.unlock();
}
}
因为这个Worker不是单例的,也就是说每次都新建一个Worker类,而且内部的锁也是NEW的实例。这样加不加锁没有区别。
让我不思其解,直到看到
另一处为interruptIfIdle方法,才明白原来是这样用的。
void interruptIfIdle() {
final ReentrantLock runLock = this.runLock;
if (runLock.tryLock()) {
try {
if (thread != Thread.currentThread())
thread.interrupt();
} finally {
runLock.unlock();
}
}
}
这里的runLock.tryLock为如果拿到锁,说明当前Worker线程没有处于RUNNING状态,可进行线程中断。
如果没有拿到锁,说明Worker正在执行任务。
这个问题主要是阅读代码的时候不够仔细, 还有就是经验主义想当然的认为锁是在经验范围内的用法。