为什么Java Thread没有收到中断标志?

时间:2016-12-20 23:01:37

标签: java multithreading interrupt executorservice threadpoolexecutor

我试图了解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);

有谁知道我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

来自Javadoc

  

InterruptedException - 如果有任何线程中断了当前线程。抛出此异常时,当前线程的中断状态为清除。 [我的重点]

NB没有什么可以确保线程被shutdownNow()中断。它只是将其描述为一种典型的实施方式。

你的代码有点奇怪。试试这个:

try
{
    Thread.sleep(5000L);
}
catch (InterruptedException exc)
{
    break;
}

并删除Thread.interrupted()测试。

答案 1 :(得分:0)

阅读Javadoc on Thread.sleep()

  

<强>抛出:   ...   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();
    }
}