我试图了解ExecutorService中的线程中断,我无法弄清楚为什么以下MyNeverEndingRunnable类没有得到中断信号。我有一个实现Runnable的类,只需在循环中打印和等待,直到它被中断:
class MyNeverEndingRunnable
implements Runnable
{
int count = 0;
@Override
public void run()
{
while (true)
{
System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
try { Thread.sleep(5000L); } catch (Exception ignored) {}
if (Thread.interrupted())
{
break;
}
}
}
}
我生成了一些这样的线程,然后在我的ExecutorService上调用shutdownNow(),它应该在每个正在运行的线程上调用interrupt,但下面的代码会继续运行:
int threadCount = 5;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
Future[] threads = new Future[threadCount];
for (int k = 0; k < threadCount; ++k)
{
threads[k] = executorService.submit(new MyNeverEndingRunnable());
}
Thread.sleep(20000L);
executorService.shutdownNow();
while (!executorService.isShutdown()) Thread.sleep(1000L);
有谁知道我在这里做错了什么?
答案 0 :(得分:3)
来自Javadoc:
InterruptedException
- 如果有任何线程中断了当前线程。抛出此异常时,当前线程的中断状态为清除。 [我的重点]
NB没有什么可以确保线程被shutdownNow()
中断。它只是将其描述为一种典型的实施方式。
你的代码有点奇怪。试试这个:
try
{
Thread.sleep(5000L);
}
catch (InterruptedException exc)
{
break;
}
并删除Thread.interrupted()
测试。
答案 1 :(得分:0)
<强>抛出:强> ... InterruptedException - 如果有任何线程中断了当前线程。抛出此异常时,将清除当前线程的中断状态。
一旦抛出异常,它就不会被打断。在你的情况下,你可以立即突破循环并让线程死掉,就像@EJP建议的那样。但是,如果您的代码没有线程的所有权(例如,单独的方法),您将要确保通过传播异常或重新中断来将中断传播给调用者:
try {
while (true) {
System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
Thread.sleep(5000L);
}
} catch (InterruptedException notIgnored)
Thread.currentThread().interrupt();
}
或类似地:
while (!Thread.currentThread().isInterrupted()) {
System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
try {
Thread.sleep(5000L);
} catch (InterruptedException notIgnored)
Thread.currentThread().interrupt();
}
}