执行程序关闭后,为什么Runnable仍然在可执行的线程池执行程序中执行?
我有一个可以使用的线程池执行程序实现,就像在ThreadPoolExecutor类的文档中一样。我有一个简单的测试执行以下操作:执行程序关闭后,为什么Runnable仍然在可执行的线程池执行程序中执行?
class PausableThreadPoolExecutor extends ThreadPoolExecutor {
public static PausableThreadPoolExecutor newSingleThreadExecutor() {
return new PausableThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/** isPaused */
private boolean isPaused;
/** pauseLock */
private ReentrantLock pauseLock = new ReentrantLock();
/** unpaused */
private Condition unpaused = this.pauseLock.newCondition();
public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
this.pauseLock.lock();
try {
while (this.isPaused) {
this.unpaused.await();
}
} catch (InterruptedException ie) {
t.interrupt();
} finally {
this.pauseLock.unlock();
}
}
public void pause() {
this.pauseLock.lock();
try {
this.isPaused = true;
} finally {
this.pauseLock.unlock();
}
}
public void resume() {
this.pauseLock.lock();
try {
this.isPaused = false;
this.unpaused.signalAll();
} finally {
this.pauseLock.unlock();
}
}
public static void main(String[] args) {
PausableThreadPoolExecutor p = PausableThreadPoolExecutor.newSingleThreadExecutor();
p.pause();
p.execute(new Runnable() {
public void run() {
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
});
p.shutdownNow();
}
}
有趣的是调用shutdownNow时会引起了Runnable运行。这是正常的吗?据我了解,shutDownNow将尝试通过中断它们来停止正在执行的任务。但中断似乎唤醒了执行它的任务。有人可以解释这个吗?
有趣的是,对shutDownNow的调用将导致Runnable运行。这是正常的吗?
不确定这是“正常”,但它肯定会给你的代码。在你beforeExecute(...)
方法我看到以下内容:
this.pauseLock.lock();
try {
while (this.isPaused) {
this.unpaused.await();
}
} catch (InterruptedException ie) {
t.interrupt();
} finally {
this.pauseLock.unlock();
}
作业将LOPP等待isPaused
布尔值设置为false。但是,如果作业中断,则this.unpaused.await()
将抛出InterruptedException
,这突破while
循环,线程将重新中断,这总是一个好的模式,返回beforeExecute()
,并允许执行作业。除非你有特定的代码来处理中断,否则中断一个线程不会中止它。
如果要停止作业时被中断,那么你可以扔RuntimeException
在beforeExecute()
处理程序,当你看到作业作为被中断:
} catch (InterruptedException ie) {
t.interrupt();
throw new RuntimeException("Thread was interrupted so don't run");
一个清洁的方法可能是检查看看你是在run()
方法打断,然后退出:
public void run() {
if (Thread.currentThread().isInterrupted()) {
return;
}
...
清除,谢谢你的回应。 –
当你调用关机是中断工作者线程,这并不意味着它会立即停止。它取决于逻辑,以及如何使用间代码中的破裂标志 –