15

我正在尝试关闭线程池中的所有线程。

通常我会尝试:

        while(!Thread.currentThread().isInterrupted()) {...

要关闭 while 循环...

但我有一个线程,它只包含大约

        while(!Thread.currentThread().isInterrupted()) {//which is true

这就是我关闭线程的方式:

pool.shutdownNow();

那么你将如何关闭这样的线程呢?

4

4 回答 4

16

您可以添加一个volatile布尔值flag

public class Worker implements Runnable {

    volatile boolean cancel = false;
    @Override
    public void run() {

        while (!cancel) {
            // Do Something here
        }
    }

    public void cancel() {
        cancel = true;
    }
}

现在你可以打电话

worker.cancel();

更新:

来自shutdownNow()的 Java 文档

尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。

除了尽最大努力停止处理正在执行的任务之外,这里没有任何保证。例如,典型的实现将通过Thread.interrupt()取消,因此任何未能响应中断的任务可能永远不会终止

因此,要么您必须通过保留中断来定义您的中断策略

  catch (InterruptedException ie) {
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
于 2012-10-29T10:56:54.877 回答
2

取而代之的是,您可以使用自创标志作为 while 循环的条件。

public class MyClass implements Runnable
{

    private volatile boolean running = true;

    public void stopRunning()
    {
        running = false;
    }

    public void run()
    {
        while (running)
        {

        }
        // shutdown stuff here
    }

}

现在,要停止它,只需调用:

myClassObject.stopRunning();

这将使代码正常完成。

于 2012-10-29T10:55:38.677 回答
2

如果您已按照您的描述实现了此功能,那么它应该可以正常工作。

当您调用pool.shutdownNow()它时,它应该中断当前处于活动状态的所有工作线程。假设应用程序特定的run()方法检查中断标志并在发现它设置时自行终止,您的线程应该关闭。

确实没有必要使用临时取消标志添加不同的机制......或类似的东西。


顺便说一句,有几个原因interrupt()临时取消更好:

  • ExecutorService 等标准 API 使用它。
  • 各种低级 API 方法(如sleepwaitjoin和一些 I/O 方法对它很敏感。
于 2012-10-29T11:09:27.137 回答
1

如果您使用的是ExecutorService 实现,那么它肯定会向其线程池中的所有线程java.util.concurrent发送信号。interrupt您的流氓任务的问题可能是循环实际上并没有迭代,而是在其中的某个地方阻塞,因此interrupted根本没有检查状态。

您可能遇到的另一个问题:while 循环运行了一些代码,这些代码在没有正确处理的情况下捕获了 InterruptedException ,从而有效地吞下了中断信号。这是一个常见的编码错误,在大多数情况下是由于检查了丑陋的事实InterruptedException

于 2012-10-29T11:08:38.287 回答