如何在没有任何用处的情况下停止永远运行的线程
在下面的代码中,我有一个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非常善良,它会通过将InterruptedException
从sleep()
抛出来通知你。 抓住它并打破你的循环。 而已!
至于其他建议:
- 关于Thread.stop() :
不推荐 。 这种方法本质上是不安全的[…]
- 添加自己的标志并密切关注它(只记得使用
AtomicBoolean
或volatile
!),但是为什么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要么处理一个有效的特殊情况……或者他们很幸运。