如何gracefully停止java线程?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (29)

我写了一个线程,它花费了太多的时间来执行,看起来并没有完全完成。我想gracefully地停止线程。该怎么弄?

提问于
用户回答回答于

要做到这一点的方法是让run()线程保护一个boolean变量,并true在需要停止时从外部设置它,如下所示:

class MyThread extends Thread
{
  volatile boolean finished = false;

  public void stopMe()
  {
    finished = true;
  }

  public void run()
  {
    while (!finished)
    {
      //do dirty work
    }
  }
}

曾经有一种stop()方法存在,但正如文档所述

这种方法本质上是不安全的。使用Thread.stop停止线程会导致它解锁所有已锁定的监视器(作为未检查的ThreadDeath异常向上传播的自然结果)。如果之前由这些监视器保护的对象处于不一致状态,则受损对象变为对其他线程可见,可能导致任意行为。

用户回答回答于

关于使用标志停止线程的坏处是,如果线程正在等待或正在睡眠,那么您必须等待它完成等待/睡眠。如果您在线程中调用中断方法,那么会导致等待或睡眠呼叫以InterruptedException退出。

调用interrupt()还会设置一个中断属性,您可以将其用作标志来检查是否退出(如果线程未等待或正在休眠)。

您可以编写线程的运行方法,以便在线程正在执行的任何循环逻辑之外捕获InterruptedException,或者可以捕获循环内的异常并接近引发异常的调用,将catch块中的中断标志设置为InterruptedException,以便线程不会丢失它被中断的事实。中断的线程仍然可以保持控制并按照自己的条件完成处理。

假设我想编写一个工作线程,该工作线程以增量方式工作,出于某种原因,中间有一个睡眠中断,并且我不希望退出睡眠状态而不处理该增量的剩余工作而退出处理,我只想如果它处于中间增量中,则退出:

class MyThread extends Thread
{
    public void run()
    {
        while (!Thread.currentThread().isInterrupted())
        {
            doFirstPartOfIncrement();
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                // restore interrupt flag
                Thread.currentThread().interrupt();
            }
            doSecondPartOfIncrement();
        }
    }
}

扫码关注云+社区