如何优雅地停止Java线程?

我写了一个线程,执行的时间太长,看起来还没有完全完成。 我想优雅地停止线程。 任何帮助?

要做到这一点的方法是让线程的run()由一个booleanvariables来保护,当你想停止它的时候,把它设置为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停止线程会导致它解锁所有已locking的监视器(作为未检查的ThreadDeathexception向上传播的自然结果)。 如果之前由这些监视器保护的任何对象处于不一致状态,则损坏的对象对其他线程变得可见,可能导致任意行为。

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

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

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

您可以编写线程的run方法,以便在线程正在执行的任何循环逻辑之外捕获InterruptedException,或者可以在循环内捕获exception并接近抛出exception的调用,将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方法中的return语句。 或者你可以检查线程是否已经中断,然后取消它的工作。 Fe:

 while (!isInterrupted()) { // doStuff } 

做一个易变的布尔stop某处。 然后在线程中运行的代码中,定期执行

  if (stop) // end gracefully by breaking out of loop or whatever 

要停止线程,请将stop设置为true

我认为你必须这样手动进行。 毕竟,只有在线程中运行的代码才知道什么是和不是优雅的。

您需要发送停止消息给线程,线程本身需要采取行动,如果消息已收到。 如果长时间运行在循环内,这很容易:

 public class StoppableThread extends Thread { private volatile boolean stop = false; public void stopGracefully() { stop = true; } public void run() { boolean finished = false; while (!stop && !finished) { // long running action - finished will be true once work is done } } } 

对于一个阻止自己的线程,似乎没有人提到(错误)使用exception:

 abstract class SelfStoppingThread extends Thread { @Override public final void run() { try { doRun(); } catch (final Stop stop) { //optional logging } } abstract void doRun(); protected final void stopSelf() { throw new Stop(); } private static final class Stop extends RuntimeException {}; } 

子类只需要像使用线程一样重写doRun(),并在感觉想要停止时调用stopSelf()。 IMO感觉比在一个while循环中使用一个标志更清洁。