如何优雅地停止java线程?

Use*_*034 65 java multithreading

我写了一个帖子,它花了太多时间执行,似乎没有完全完成.我想优雅地停止线程.有帮助吗?

Jac*_*ack 68

执行此操作的方法是让run()一个boolean变量保护线程,并true在需要停止时将其设置为外部,例如:

class MyThread extends Thread
{
  volatile boolean finished = false;

  public void stopMe()
  {
    finished = true;
  }

  public void run()
  {
    while (!finished)
    {
      //do dirty work
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

曾几何时,一种stop()方法存在,但正如文件所述

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

这就是为什么你应该有一个警卫..

  • 请参阅Jon Skeet对Bart的回答的评论 - 它也适用于你的. (2认同)
  • 这已经使内置的interrupt()和isInterrupted()方法加倍. (2认同)

Nat*_*hes 12

有关使用一个标志,停止你的线程坏的部分是,如果线程正在等待或再睡觉,你必须等待它完成等待/睡眠.如果调用线程中断方法,然后将导致等待或睡眠电话与一个InterruptedException退出.

(有关标志的方法的第二个坏的部分是最平凡的代码将被利用像java.util.concurrent中,所在班是专门为使用中断取消库.尝试使用手卷在任务标志传递进入执行者会很尴尬.)

调用中断()还规定,您可以使用作为一个标志,检查是否退出(在线程没有等待或休眠的事件)中断的特性.

您可以编写线程的run方法,以便在线程正在执行的任何循环逻辑之外捕获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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是对类似问题的回答,包括示例代码.


Xor*_*rty 10

你不应该从其他人那里杀死Thread.这被认为是一种相当糟糕的习惯.但是,有很多方法.您可以使用returnthread run方法中的语句.或者您可以检查线程是否已被中断,然后它将取消它的工作.铁:

while (!isInterrupted()) { 
  // doStuff
}
Run Code Online (Sandbox Code Playgroud)

  • 你可以使用带有void返回类型的空return语句,方法将结束 (3认同)

Bar*_*lom 5

在某处创建一个易失性布尔值stop。然后在线程中运行的代码中,定期执行

 if (stop) // end gracefully by breaking out of loop or whatever
Run Code Online (Sandbox Code Playgroud)

要停止线程,请设置stoptrue

我认为你必须以这种方式手动完成。毕竟,只有在线程中运行的代码才知道什么是优雅的,什么是不优雅的。

  • 请注意,您需要使用锁定或使字段可变,以确保读取线程看到写入线程的更改。 (22认同)
  • @Bart:实际上,可能根本不长。理论上,永远。 (6认同)