为什么 线程池中正在执行任务的线程 不可以被中断?
这篇文章写的挺好的
https://juejin.cn/post/684490...
其中 Worker的runWorker方法中 在执行任务之前使用了 lock方法获取锁,任务执行结束之后再释放锁。这个锁的主要作用就是 避免线程池关闭线程时对正在执行任务的线程进行中断操作。
final void runWorker(Worker w) { Thread wt = Thread.currentThread();
//获取第一个任务
Runnable task = w.firstTask;
w.firstTask = null;
//允许中断
w.unlock();
//是否因异常退出循环
boolean completedAbruptly = true;
try {
//如果task为空,则通过getTask来获取任务
while (task != null || (task = getTask()) != null) {
w.lock();
/**
* 如果线程池正在停止,那么要保证当前线程时中断状态;
* 如果不是的话,则要保证当前线程不是中断状态
*/
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
//beforeExecute和afterExecute是留给子类来实现的
beforeExecute(wt, task);
Throwable thrown = null;
try {
//通过任务方式执行,不是线程方式
task.run();
} catch (RuntimeException x) {
thrown = x;
throw x;
} catch (Error x) {
thrown = x;
throw x;
} catch (Throwable x) {
thrown = x;
throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
//processWorkerExit会对completedAbruptly进行判断,表示在执行过程中是否出现异常
processWorkerExit(w, completedAbruptly);
}
}
基于以上内容有两个问题:
(1) 如果一个线程 正在运行,他不会主动检查线程的中断状态, 也不会执行能够抛出中断异常的阻塞方法, 那么 其他线程对这个线程发起中断 ,这个被中断的线程 应该感知不到 也不会退出线程,中断是一种协作机制,其他线程发起中断如果我不主动检测是感知不到中断,也不会退出线程。 我的这个理解是否正确?
(2)为什么线程池中的线程 在执行任务的时候 要避免 这个线程被中断?
按照我的理解,基于第一点的原因,我觉的 正在执行任务的线程允许中断也无妨,因为从源码的内容来看,线程能否响应这个中断 取决于 用户的任务 task的run方法中是否 存在对中断的主动检查 以及是否会执行能够抛出中断异常的方法。
补充内容:
/** * Interrupts threads that might be waiting for tasks (as
* indicated by not being locked) so they can check for
* termination or configuration changes. Ignores
* SecurityExceptions (in which case some threads may remain
* uninterrupted).
*
* @param onlyOne If true, interrupt at most one worker. This is
* called only from tryTerminate when termination is otherwise
* enabled but there are still other workers. In this case, at
* most one waiting worker is interrupted to propagate shutdown
* signals in case all threads are currently waiting.
* Interrupting any arbitrary thread ensures that newly arriving
* workers since shutdown began will also eventually exit.
* To guarantee eventual termination, it suffices to always
* interrupt only one idle worker, but shutdown() interrupts all
* idle workers so that redundant workers exit promptly, not
* waiting for a straggler task to finish.
*/
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
//这个地方 w.tryLock 检测 woker的锁是否已经处于locked状态
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
回答:
(1) 中断是可以被响应的,比如sleep,lock 的 一些方法等。其余的则需要自己自己主动检测响应。
(2) 我考虑了下,我觉得很有可能是怕影响同线程的其他任务,如果在运行过程中不清楚,由同一个线程执行的其他任务中,一旦在开头执行中断检测,就莫名其妙的退出了任务。毕竟核心线程就那么多,某一个任务中的中断,可能随机影响其他许许多多的任务。
以上是 为什么 线程池中正在执行任务的线程 不可以被中断? 的全部内容, 来源链接: utcz.com/p/944376.html