在Java中,线程不会被杀死,但是线程的停止是在 cooperative way 中完成的 . 要求线程终止,然后线程可以正常关闭 .
通常使用 volatile boolean 字段,线程定期检查并在设置为相应值时终止 .
我 would not 使用 boolean 来检查线程是否应该 terminate . 如果你使用 volatile 作为字段修饰符,这将是可靠的,但如果你的代码变得更复杂,而是使用 while 循环内的其他阻塞方法,可能会发生,你的代码将完全 not terminate 或至少 takes longer 可能想要 .
某些阻塞库方法支持中断 .
每个线程都有一个布尔标志 interrupted status ,你应该使用它 . 它可以像这样实现:
public void run() {
try {
while (!interrupted()) {
// ...
}
} catch (InterruptedException consumed)
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
Class Outer {
public static volatile flag = true;
Outer() {
new Test().start();
}
class Test extends Thread {
public void run() {
while (Outer.flag) {
//do stuff here
}
}
}
}
Thread f = <A thread to be stopped>
Method m = Thread.class.getDeclaredMethod( "stop0" , new Class[]{Object.class} );
m.setAccessible( true );
m.invoke( f , new ThreadDeath() );
14 回答
见thread by Sun on why they deprecated Thread.stop() . 它详细说明了为什么这是一个糟糕的方法以及应该采取什么措施来安全地停止线程 .
他们推荐的方法是使用共享变量作为标志,要求后台线程停止 . 然后,该变量可以由请求线程终止的不同对象设置 .
一般你不..
你要求它使用Thread.interrupt() (javadoc link)打断它正在做的事情
一个很好的解释为什么在javadoc here (java technote link)
在Java中,线程不会被杀死,但是线程的停止是在 cooperative way 中完成的 . 要求线程终止,然后线程可以正常关闭 .
通常使用
volatile boolean
字段,线程定期检查并在设置为相应值时终止 .我 would not 使用
boolean
来检查线程是否应该 terminate . 如果你使用volatile
作为字段修饰符,这将是可靠的,但如果你的代码变得更复杂,而是使用while
循环内的其他阻塞方法,可能会发生,你的代码将完全 not terminate 或至少 takes longer 可能想要 .每个线程都有一个布尔标志 interrupted status ,你应该使用它 . 它可以像这样实现:
源代码改编自Java Concurrency in Practice . 由于
cancel()
方法是公共的,您可以让另一个线程根据需要调用此方法 .一种方法是设置一个类变量并将其用作哨兵 .
在上面的例子中设置一个外部类变量,即flag = true . 将其设置为false以“杀死”该线程 .
有一种方法可以做到这一点 . 但是如果你不得不使用它,要么你是一个糟糕的程序员,要么你正在使用由坏程序员编写的代码 . 所以,你应该考虑停止成为一个糟糕的程序员或停止使用这个糟糕的代码 . 此解决方案仅适用于没有其他方式的情况 .
我想根据已经积累的评论添加几个观察结果 .
如果安全管理器允许,
Thread.stop()将停止一个线程 .
Thread.stop()很危险 . 话虽如此,如果您在JEE环境中工作并且您无法控制所调用的代码,则可能是必要的 .
您永远不应该停止停止容器工作线程 . 如果你想运行倾向于挂起的代码,(小心)启动一个新的守护程序线程并对其进行监视,必要时进行查杀 .
stop()在调用线程上创建一个新的ThreadDeath错误,然后将该错误应用于目标线程 . 因此,堆栈跟踪通常毫无 Value .
在JRE 6中,stop()检查安全管理器,然后调用调用stop0()的stop1() . stop0()是本机代码 .
我投票给
Thread.stop()
.例如,您有一个持久的操作(如网络请求) . 据说您正在等待响应,但可能需要一些时间并且用户导航到其他UI . 这个等待的线程现在是a)无用的b)潜在的问题,因为当他得到结果时,它完全没用,并且他将触发可能导致错误数量的回调 .
所有这一切,他可以进行可能CPU密集的响应处理 . 而且,作为开发人员,你甚至无法阻止它,因为你不能在所有代码中抛出
if (Thread.currentThread().isInterrupted())
行 .所以无法强行停止一个奇怪的线程 .
问题相当模糊 . 如果你的意思是“如何编写一个程序,以便在我想要的时候线程停止运行”,那么其他各种响应应该会有所帮助 . 但是,如果你的意思是“我有一个服务器的紧急情况,我现在无法重启,我只需要一个特定的线程就可以死”,那么你需要一个干预工具来匹配监控工具,如
jstack
.为此我创建了jkillthread . 请参阅其使用说明 .
当然,您正在运行某种不完全信任的代码 . (我个人有这个允许上传的脚本在我的Java环境中执行 . 是的,到处都有安全警报响铃,但它是应用程序的一部分 . )在这个不幸的例子中,你首先要求脚本编写者充满希望尊重某种布尔运行/不运行信号 . 你唯一体面的失败保障是打电话给停止方法例如,它运行的时间超过某些超时 .
但是,这只是“体面”,而不是绝对的,因为代码可以捕获ThreadDeath错误(或者你明确抛出的任何异常),而不是像一个绅士的线程那样重新抛出它 . 所以,底线是AFAIA,没有绝对的失败安全 .
没有办法优雅地杀死一个线程 .
您可以尝试中断线程,一个公共策略是使用毒丸来消息线程停止自己
}
http://anandsekar.github.io/cancel-support-for-threads/
通常,您不会杀死,停止或中断线程(或检查它是否被中断()),但让它自然终止 .
很简单 . 您可以在run()方法中使用任何循环和(volatile)布尔变量来控制线程的活动 . 您也可以从活动线程返回到主线程以停止它 .
这样你就可以优雅地杀死一个线程:) .
突然线程终止的尝试是众所周知的糟糕编程实践和应用程序设计不良的证据 . 多线程应用程序中的所有线程显式和隐式地共享相同的进程状态,并被迫相互协作以保持一致,否则您的应用程序将容易出现很难诊断的错误 . 因此,开发人员有责任通过仔细而清晰的应用程序设计来保证这种一致性 .
受控线程终端有两种主要的正确解决方案:
使用共享易失性标志
使用Thread.interrupt()和Thread.interrupted()方法 .
有关突发线程终止的问题的详细解释以及受控线程终止的错误和正确解决方案示例可在此处找到:
https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads
这里有几个关于这个主题的好读物:
What Do You Do With InterruptedException?
Shutting down threads cleanly
我没有让中断在Android中工作,所以我使用这个方法,完美地工作: