为何runWorker中在task被当前worker中的当前线程获取到准备执行task时需要进行worker.lock()?
如下图:
1、某个worker中的run逻辑只会被worker中包装的线程进行执行;
2、按理说:不会存在多个线程并发执行同一个worker中的runWorker()逻辑,那么为什么需要在当前线程已经获取到task后进行w.lock()操作呢?
其实原因是:当前worker如果正在执行某个task任务逻辑,那么worker其实是属于被上锁(就是当前worker锁)的阶段。那么外部线程-比如main线程,想要进行线程池shutdown操作,操作worker时就可以提供针对worker同步的能力:
如上可以知道:worker中线程正在处理任务时,shutdown()逻辑中获取worker锁会失败,那么无法进行线程中断;
线程池 executor.shutdown() 跟 executor.shutdownNow()的区别
在 Java 中,executor.shutdown()
和 executor.shutdownNow()
都是用来关闭线程池的方法,但它们之间有一些区别:
-
executor.shutdown()
: 调用该方法后,线程池将不再接受新的任务提交,但会等待已经提交的任务执行完成(包括等待队列中的任务)。线程池会逐渐关闭,直到所有任务都执行完毕,最终线程池被关闭。 -
executor.shutdownNow()
: 调用该方法后,线程池会尝试立即关闭,它会尝试中断正在执行的任务,并清空任务队列,未执行的任务会被移除。这可能会导致一些任务无法执行完成。
总的来说,executor.shutdown()
是一个温和的关闭线程池的方式,它会等待任务执行完成;而 executor.shutdownNow()
则是一种强制关闭线程池的方式,它会尝试立即关闭线程池,可能会导致部分任务无法执行完成。
在选择使用哪种方法时,根据实际情况考虑是否需要等待任务执行完成以及是否允许部分任务被丢弃。
executor.shutdownNow() 会立刻将线程池中的线程停止么?比如线程-1正在处理某个任务逻辑中
executor.shutdownNow()
方法会尝试立即关闭线程池,包括中断正在执行的任务和清空任务队列。但是需要注意的是,对于正在执行的任务,线程池会尝试中断它们,但并不能保证一定能够立即停止执行。具体来说:
-
如果任务是可中断的(即任务内部响应中断),那么
shutdownNow()
会发送中断信号给任务,任务有可能会被中断,停止执行。 -
如果任务不是可中断的,那么
shutdownNow()
只能等待任务执行完成。这种情况下,即使调用了shutdownNow()
方法,任务仍然会继续执行直到完成。
因此,shutdownNow()
方法并不能保证立即停止线程池中所有线程的执行,特别是对于不可中断的任务。它会尽最大努力去停止线程的执行,但无法完全保证。
1、中断所有worker中的线程;
2、从队列中排出所有等待中的任务;
worker中的线程什么时候会执行完?
关键点在getTask()什么时候返回null?
在给定的代码中,getTask()
方法是用来获取任务的。在这个方法中,根据一系列条件判断,可能会返回 null
。下面是可能导致返回 null
的情况:
1、如果线程池的运行状态 rs
大于等于 SHUTDOWN
并且队列为空,或者 rs
大于等于 STOP
并且队列为空,这表示线程池已经处于关闭状态并且队列为空,那么会递减工作线程计数并返回 null
。
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
2、如果工作线程数 wc
大于最大线程数 maximumPoolSize
或者允许核心线程超时(allowCoreThreadTimeOut
为 true)且 timedOut
为 true,并且(工作线程数大于1 或者 队列为空),那么会尝试递减工作线程计数并返回 null
。
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}