如何在没有任何用处的情况下停止永远运行的线程

在下面的代码中,我有一个while(true)循环。 考虑到try块中存在一些代码的情况,其中线程应该执行一些约需一分钟的任务,但是由于某些预期的问题,它正在运行。 我们可以阻止那个线程吗?


public class thread1 implements Runnable { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub thread1 t1 = new thread1(); t1.run(); } @Override public void run() { // TODO Auto-generated method stub while(true){ try{ Thread.sleep(10); } catch(Exception e){ e.printStackTrace(); } } } } 

首先,你没有在这里开始任何线程! 你应该创建一个新的线程,并将你容易混淆的名称thread1 Runnable传递给它:

 thread1 t1 = new thread1(); final Thread thread = new Thread(t1); thread.start(); 

现在,当你真的有一个线程时,有一个内置的function来中断正在运行的线程,叫做… interrupt()

 thread.interrupt(); 

但是,单独设置此标志不起作用,您必须在正在运行的线程中处理此问题:

 while(!Thread.currentThread().isInterrupted()){ try{ Thread.sleep(10); } catch(InterruptedException e){ Thread.currentThread().interrupt(); break; //optional, since the while loop conditional should detect the interrupted state } catch(Exception e){ e.printStackTrace(); } 

有两点需要注意: while循环现在会在thread isInterrupted()时结束。 但是如果线程在睡眠期间被中断,那么JVM非常善良,它会通过将InterruptedExceptionsleep()抛出来通知你。 抓住它并打破你的循环。 而已!


至于其他建议:

  • 关于Thread.stop() :

不推荐 。 这种方法本质上是不安全的[…]

  • 添加自己的标志并密切关注它(只记得使用AtomicBooleanvolatile !),但是为什么JDK已经为你提供了这样的内置标志呢? 额外的好处是打断sleep ,使线程中断更具响应性。

停止线程的正确方法是interrupt它(不推荐使用stop()并且可能有令人讨厌的副作用):

 t1.interrupt() 

这将导致Thread.sleep()Object.wait()等方法抛出InterruptedException

然后只需为此exception添加一个catch块,然后简单地退出while循环。

编辑:我现在意识到你的无限循环在主线程中运行,没有你的代码创建的线程,它只是run() ning一个Runnable 。 您需要在某个时刻调用Thread.start()来生成新线程。

创建一个字段boolean keepGoing ,在开始线程之前设置为true ,并用while (keepGoing)替换while (true) while (keepGoing) 。 在某些时候,你决定在哪里,只需将keepGoing的值改为false ,它就会退出循环。

停止任意线程的唯一方法是中断它。 保持对它的引用然后调用中断方法。

将catch中断移到循环外部。 这不再需要任何代码行,它只是正确处理中断,即操作被中断。

 public void run() { try{ while(true) { Thread.sleep(10); } } catch(InterruptedException e){ System.out.println("Thread interrupted")); } } 

我建议使用Thread.interrupt() (如@Bohemian所述)。 与使用ad-hoc标志相比,它有几个优点:

  • 您无需创建和使用特定于应用程序的API来执行此操作。 (中断保证线程安全……)

  • Thread.interrupt()将中断在wait()join中阻塞的线程,或者可能中断一些阻塞I / O调用。

但是,它不是一个神奇的子弹。 如果您尝试停止的线程正在执行常规代码,则需要定期检查其interrupted()标志,否则不会停止。 这使得我们和船一样处于ad-hoc标志机制中。 线程必须合作,否则无法(安全地)停止。

1 – 这是一个阴暗的地方。 一方面,有一个InterruptedIOException其javadoc表示“信号I / O操作已被中断” 另一方面,javadocs中没有为各种java.io流类明确提到exception。


确实,某些第三方代码可能无法正确处理interrupted标志,因此中断可能会被“吃掉”。 但是如果你有源代码,你可以检查一下。 并且情况与不关注您的ad-hoc标记机制的第三方代码没有太大区别。


建议使用Thread.stop() 。 它从根本上说是好看的。 有些人声称它适用于他们,但IMO要么处理一个有效的特殊情况……或者他们很幸运。