【问题标题】:How to kill a thread which has a while(true)?如何杀死有一段时间(真)的线程?
【发布时间】:2012-10-18 16:21:00
【问题描述】:

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

通常我会尝试:

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

关闭while循环...

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

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

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

pool.shutdownNow();

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

【问题讨论】:

  • 你需要知道那个线程的退出条件......
  • 当你在你的extends Thread类的方法中有上述while循环时,你可以使用this.isInterrupted()而不是Thread.currentThread().isInterrupted()
  • @Philipp 希望 OP 不会扩展 Thread
  • @Philipp 这是一种被广泛接受的最佳实践。只需谷歌搜索“java 扩展线程”即可找到所有相关信息。这些教程显然是在伤害他们的读者。
  • @Philipp 官方文档不是要推荐的,而是要...好吧,document,在这种情况下,确实有两种方法可以提供条目指向Thread 实例。

标签: java multithreading thread-safety threadpool


【解决方案1】:

您可以添加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();
   }

【讨论】:

  • -1 这是多余的——为什么不只使用中断机制呢?
  • @AmitD 你确实需要那个否定:)
  • @MarkoTopolnik 他有一个线程的中断状态为假,因此如果有否定,它将永远不会进入。我认为措辞有所不同。
  • @AmitD 没有关注你。 (interrupt==false) => (!interrupt true),所以条件始终为真。 OP 绝对不会因为永远不会进入循环而受到影响,而是因为无法打破它。
  • 在我看来,第一行建议是“检查它被吞下的位置”,并且仅作为最后的解决方法使用自定义机制,因为这涉及更多代码,为代码带来新的方式失败。
【解决方案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();

这会让代码正常完成。

【讨论】:

    【解决方案3】:

    如果您按照您的描述实现了这个,它应该可以工作。

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

    确实没有必要使用 ad hoc 取消标志...或类似的方式添加不同的机制。


    顺便说一句,interrupt() 优于 ad hoc 取消的原因有两个:

    • ExecutorService 等标准 API 使用它。
    • 各种低级 API 方法,如 sleepwaitjoin 和一些 I/O 方法对其敏感。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • @assylias 呵呵,不只是今天 :)
      猜你喜欢
      • 1970-01-01
      • 2017-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多