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

Why doesn't Java Thread receive interrupt flag?

我试图了解 ExecutorService 中的中断线程,但我无法弄清楚为什么以下 MyNeverEndingRunnable class 没有获得中断信号。我有一个 class 实现了 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() ,它应该在每个 运行ning 线程上调用中断,但下面的代码将永远 运行 继续:

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);

有人知道我做错了什么吗?

来自Javadoc

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown. [My emphasis]

NB 没有任何东西可以真正保证线程被 shutdownNow() 中断。它只是将其描述为 'typical implementation'.

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

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

并删除 Thread.interrupted() 测试。

阅读 Javadoc on Thread.sleep():

Throws: ... InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

一抛出异常,就不再中断了。在您的情况下,您可以立即跳出循环并让线程终止,正如@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();
    }
}