你如何杀死Java中的java.lang.Thread?
-
到现在为止你无法杀死一个线程;因为容易发生死锁,所以从未实现destroy()
-
我更喜欢关于ExecutorStatus这个问题的答案:stackoverflow.com/questions/2275443/how-to-timeout-a-thread
-
@loungerdork"我认为Java应该为你无法控制的失控线程实现一个安全停止/销毁方法,尽管有失去锁和其他陷阱的警告"所以你想要一个不安全的线程停止。我想你已经有了一个。
-
令人惊讶的是,2009年将会有什么样的问题得到212票。这将立即被摧毁。
-
@JonathonReinhart:为什么?这似乎是一个合法的问题,即便是这些日子。也许你不知道当你有失控的线程时它会导致的挫败感,并且只能使用弃用的函数以某种方式处理它?
-
@JonathonReinhart AFAIK越来越多的服务正在变得混合并使用托管环境来执行他们没有完全控制代码的第三方代码(插件,脚本等),完全采取thread.stop关闭似乎是不合理的。表,因为对于服务工程师来说,由于挂起(带走线程)或繁忙的无限循环(带走核心),实时服务状态可以比非服务状态无限好,状态腐败问题是对于每个查询状态的数据服务服务来说,数据完整性并不是最重要的,这并不是什么大问题
-
我认为这很有意思,因为while(true)比while(运行)快一点但是没有办法在没有检查循环中某个字段的情况下离开while(true)。
请参阅Sun的这个主题,了解他们弃用的原因Thread.stop()。它详细说明了为什么这是一个糟糕的方法以及应该采取什么措施来安全地停止线程。
他们推荐的方法是使用共享变量作为标志,要求后台线程停止。然后,该变量可以由请求线程终止的不同对象设置。
-
如果你检查你已经中断的线程isAlive()它将返回true并且它们将继续添加到你当前的ThreadGroup [],你可以使用Thread.currentThread.getThreadGroup()。list();它将打印它拥有的所有线程,如果重复流程,您将看到线程的多个实例。
-
如果你在PC上然后没问题,但如果你正在开发一个移动软件(我已经体验过它的android)那么你会得到OutOfMemoryError
-
并且你不能通过ThreadGroup方法void remote(Thread t)删除它,因为它的访问是包私有的。但我个人认为你可以打电话使用反射。
-
可以/应该注意,为了确保通过标志快速通信停止请求,变量必须是易失性的(或者必须同步对变量的访问),如建议中所述。
-
此时此链接已被杀死。我能够在archive.org上找到它,但是:web.archive.org/web/20090202093154/http://java.sun.com/j2se/…
-
@codecompleting我花了大约3年的时间在大学教学和写作几乎完全用Java;)
-
如果线程正在等待某些响应怎么办?例如用户输入或套接字来接收数据?
-
我使用java.sql.DriverManager中的方法getConnection()。如果连接attemt花费的时间太长,我会尝试通过调用Thread.interrupt()来终止相应的线程,但它根本不会影响线程。然而,Thread.stop()可以工作,虽然oracle说如果interrupt()没有,它应该不起作用。我想知道如何使它工作并避免使用弃用的方法。
-
stackoverflow.com/questions/19894607/java-how-to-stop-thread/…
一般你不..
你要求它使用Thread.interrupt()(javadoc链接)中断它正在做的事情
这里有一个很好的解释为什么在javadoc(java技术说明链接)
-
@Fredrik调用interrupt()方法时,Thread上下文会发生什么?主要问题与每个新线程的日志生成有关。
-
@ABcDexter重点是中断不会中断任何事情,它只是向线程中的代码(或线程调用的代码)发出信号,表明有人要求它中断它正在做的事情。然后,该线程应该很好地停止处理并返回,就像它完成它应该做的那样(并且在那时,线程上下文可能也被丢弃)。 OTOH,如果你真的强行停止了线程,你的问题会非常好,答案也不明确。
在Java中,线程不会被杀死,但是线程的停止是以合作的方式完成的。要求线程终止,然后线程可以正常关闭。
通常使用volatile boolean字段,线程定期检查并在设置为相应值时终止。
我不会使用boolean来检查线程是否应该终止。如果你使用volatile作为字段修饰符,这将是可靠的,但如果你的代码变得更复杂,而是在while循环中使用其他阻塞方法,可能会发生,你的代码根本不会终止或至少需要更长的时间。
Certain blocking library methods support interruption.
每个线程都有一个布尔标志中断状态,你应该使用它。它可以像这样实现:
1 2 3 4 5 6 7 8 9 10 11
| public void run () {
try {
while (!interrupted ()) {
// ...
}
} catch (InterruptedException consumed )
/* Allow thread to exit */
}
}
public void cancel () { interrupt (); } |
源代码改编自Java Concurrency in Practice。由于cancel()方法是公共的,您可以让另一个线程根据需要调用此方法。
-
如果您将不受信任的代码作为插件或脚本运行,该怎么办? Java为不受信任的代码嵌入了沙箱。沙盒是无用的,它可以在没有强力停止的情况下工作。想象一下,你正在用java编写浏览器。杀死任意页面脚本的能力是无价的。
-
@ayvango然后你必须在自己的沙箱中运行该脚本。 Java沙箱保护机器不受应用程序的影响,而不是应用程序的相互部分。
-
@DavidSchwartz你的意思是,我应该使用其他平台然后java?
-
@ayvango您仍然可以使用Java沙箱来保护计算机免受应用程序的攻击。但是,如果要保护应用程序的某些部分不受应用程序的其他部分的影响,则需要选择一些可以执行此操作的工具。
-
@DavidSchwartz ASFAIK如果在平台级别不支持这样的工具则不存在。但当然,任务可以通过完全解释的脚本引擎来解决。它可以计算像erlang那样的减少量并做其他事情。
-
我尝试过这个但是相信"cancel()"是从一个不同的线程调用的,而不是"run()",并且"run(1)"在Runnable类(Java 8)上不可用。我最终将线程句柄存储到"volatile thread runningThread"(感谢volatile点)并在"cancel()"中调用"runningThread.interrupt()"。
-
interrupted()专为线程检查(并清除)自己的标志而设计。用它。检查其他线程的标志时使用isInterrupted();它只留下标志,因为线程不应该改变其他线程的状态。
一种方法是设置一个类变量并将其用作哨兵。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Class Outer {
public static volatile flag = true;
Outer () {
new Test (). start();
}
class Test extends Thread {
public void run () {
while (Outer. flag) {
//do stuff here
}
}
}
} |
在上面的例子中设置一个外部类变量,即flag = true。将其设置为false以"杀死"该线程。
-
正如一个侧面提示:一个变量作为标志只有在线程运行并且没有卡住时才起作用。 Thread.interrupt()应该让线程脱离大多数等待条件(等待,睡眠,网络读取等)。因此,您永远不应该永远不会捕获InterruptedException来使其工作。
-
这不可靠;制作"flag"volatile以确保它在任何地方都能正常工作。内部类不是静态的,因此该标志应该是一个实例变量。应该在访问器方法中清除该标志,以便可以执行其他操作(如中断)。名称"flag"不具有描述性。
-
我没有在run方法中获得"while"的东西。这是不是意味着在run方法中写入的内容将被重复?这不是我们想要线程首先要做的事情:(
-
@Sofia,是的。但是,除此之外,现在我们想要处理while的条件,以便我们可以随时将其设置为false。
-
+1执行while(!Thread.currentThread()。isInteruppted())是首选
-
这两种情况都会失败,例如你在while {// open ext process}中打开一个外部进程并且该进程被挂起,现在线程都不会被中断,也不会到达结束以检查你的布尔条件,而你是左挂...尝试用例如使用java.exec启动一个python控制台并尝试在不写出口的情况下获取控件,并查看是否有办法杀死该进程并退出....没有办法摆脱这种情况......
-
@ karim79,你知道你的解决方案是一个内存耗尽,当C ++在异常好和有效的情况下完成同样的事情。
有一种方法可以做到这一点。但是如果你不得不使用它,要么你是一个糟糕的程序员,要么你正在使用由坏程序员编写的代码。所以,你应该考虑停止成为一个糟糕的程序员或停止使用这个糟糕的代码。
此解决方案仅适用于没有其他方式的情况。
1 2 3 4
| 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() ); |
-
完全没有理由这样做,因为即使它被弃用,仍然可以调用public Thread.stop。
-
@Lii Thread.stop执行相同操作但也检查访问权限和权限。使用Thread.stop是相当明显的,我不记得为什么我使用Thread.stop0代替那个。也许Thread.stop不能用于我的特殊情况(Java 6上的Weblogic)。或者可能因为Thread.stop已弃用并导致警告。
-
在我的场景中,这是阻止无休止运行线程的唯一方法。对于某些原因.stop()没有停止线程,但是stop0()没有
我想根据已经积累的评论添加几个观察结果。
如果安全管理器允许,Thread.stop()将停止一个线程。
Thread.stop()很危险。话虽如此,如果您在JEE环境中工作并且您无法控制所调用的代码,则可能是必要的。
您永远不应该停止停止容器工作线程。如果你想运行倾向于挂起的代码,(小心)启动一个新的守护程序线程并对其进行监视,必要时进行查杀。
stop()在调用线程上创建一个新的ThreadDeath错误,然后将该错误应用于目标线程。因此,堆栈跟踪通常毫无价值。
在JRE 6中,stop()检查安全管理器,然后调用调用stop0()的stop1()。 stop0()是本机代码。
我投票给Thread.stop()。
例如,您有一个持久的操作(如网络请求)。
据说您正在等待响应,但可能需要一些时间并且用户导航到其他UI。
这个等待线程现在是a)无用的b)潜在的问题,因为当他得到结果时,它完全没用,并且他将触发可能导致错误数量的回调。
所有这一切,他可以进行可能CPU密集的响应处理。而且,作为开发人员,你甚至无法阻止它,因为你不能在所有代码中抛出if (Thread.currentThread().isInterrupted())行。
所以无法强行停止一个奇怪的线程。
-
如果网络操作已经安全中止,只需中断线程即可。如果网络操作不能安全地中止,则无论如何都无法安全地调用Thread.stop()。您没有投票支持Thread.stop(),您要求每个执行每项操作的人员可能需要很长时间才能安全地中止。这可能是一个好主意,但它与实施Thread.stop()作为请求安全堕胎的方式无关。我们已经有interrupt了。
-
@Anfet -"我投票支持Thread.stop()。" - 抱歉,Java API设计不是民主。 Thread.stop()有问题。看到接受的答案。
-
@Stephen在我看来,Java Thread API是民主的。否则我们会开箱即用Thread.kill(),但现在它更像是:"亲爱的线程,你会死吗?","好吧,我会看到我能做些什么,但没有承诺"
-
我的意思是...... Java Thread API >>设计过程<<。设计师不会影响你的想法(你的"投票")。很久以前,他们做出了一项技术上(技术上正确的)决定,他们不会改变它。
问题相当模糊。如果你的意思是"如何编写一个程序,以便在我想要的时候线程停止运行",那么其他各种响应应该会有所帮助。但是,如果你的意思是"我有一个服务器的紧急情况,我现在无法重启,我只需要一个特定的线程就可以死",那么你需要一个干预工具来匹配像jstack这样的监控工具。
为此我创建了jkillthread。请参阅其使用说明。
当然,您正在运行某种不完全信任的代码。 (我个人有这个允许上传的脚本在我的Java环境中执行。是的,到处都有安全警报响铃,但它是应用程序的一部分。)在这个不幸的例子中,你首先要求脚本编写者充满希望尊重某种布尔运行/不运行信号。你唯一合适的故障保险是在线程上调用stop方法,比如说,它运行时间超过一些超时。
但是,这只是"体面",而不是绝对的,因为代码可以捕获ThreadDeath错误(或者你明确抛出的任何异常),而不是像一个绅士的线程那样重新抛出它。所以,底线是AFAIA,没有绝对的失败安全。
-
AFAIK越来越多的服务正在变得混合并使用托管环境来执行他们无法完全控制代码的第三方代码(插件,脚本等),将thread.stop从表中删除似乎是不合理的,因为对于服务工程师来说,实时服务状态可以比非服务状态(无论是由于挂起(带走线程)还是忙碌无限循环(带走内核))无限好
没有办法优雅地杀死一个线程。
您可以尝试中断线程,一个公共策略是使用毒丸来消息线程停止自己
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class CancelSupport {
public static class CommandExecutor implements Runnable {
private BlockingQueue <String > queue ;
public static final String POISON_PILL ="stopnow";
public CommandExecutor (BlockingQueue <String > queue ) {
this. queue=queue ;
}
@Override
public void run () {
boolean stop =false;
while(!stop ) {
try {
String command =queue. take();
if(POISON_PILL. equals(command )) {
stop =true;
} else {
// do command
System. out. println(command );
}
} catch (InterruptedException e ) {
stop =true;
}
}
System. out. println("Stopping execution");
}
} |
}
1 2 3 4 5 6 7
| BlockingQueue <String > queue =new LinkedBlockingQueue <String >();
Thread t =new Thread(new CommandExecutor (queue ));
queue. put("hello");
queue. put("world");
t. start();
Thread. sleep(1000);
queue. put("stopnow"); |
http://anandsekar.github.io/cancel-support-for-threads/
通常,您不会杀死,停止或中断线程(或检查它是否被中断()),但让它自然终止。
很简单。您可以在run()方法中使用任何循环和(volatile)布尔变量来控制线程的活动。您也可以从活动线程返回到主线程以停止它。
这样你就可以优雅地杀死一个线程:)。
"杀死一个帖子"不是一个合适的短语。这是我们可以在will上实现线程的优雅完成/退出的一种方式:
我使用的Runnable:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class TaskThread implements Runnable {
boolean shouldStop ;
public TaskThread (boolean shouldStop ) {
this. shouldStop = shouldStop ;
}
@Override
public void run () {
System. out. println("Thread has started");
while (!shouldStop ) {
// do something
}
System. out. println("Thread has ended");
}
public void stop () {
shouldStop = true;
}
} |
触发类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class ThreadStop {
public static void main (String[] args ) {
System. out. println("Start");
// Start the thread
TaskThread task = new TaskThread (false);
Thread t = new Thread(task );
t. start();
// Stop the thread
task. stop();
System. out. println("End");
}
} |
这里有几个关于这个主题的好读物:
你怎么处理InterruptedException?
干净地关闭线程
突然线程终止的尝试是众所周知的错误的编程实践和应用程序设计不良的证据。多线程应用程序中的所有线程显式和隐式地共享相同的进程状态,并被迫相互合作以保持一致,否则您的应用程序将容易出现很难诊断的错误。因此,开发人员有责任通过仔细而清晰的应用程序设计来保证这种一致性。
受控线程终端有两种主要的正确解决方案:
-
使用共享易失性标志
-
使用Thread.interrupt()和Thread.interrupted()方法。
有关突发线程终止的问题的详细解释以及受控线程终止的错误和正确解决方案示例可在此处找到:
https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads
-
由于程序不再由单个开发人员编写,因此通常需要终止线程。因此不能算是糟糕的编程。我无法想象没有杀人的Linux。无法杀死线程是Java缺陷。
-
很棒,Mr. Right ...如果你不得不打电话给某个第三方库,你无法控制它,哪个有超时错误,并且在执行时可能每1000-2000次挂起一次怎么办?糟糕的编程习惯吧?那么你不能总是访问你正在使用的代码。无论如何,op在设计自己的代码时询问如何杀死一个线程而不是如何控制它的流程......
-
问题是当你杀死一个拥有互斥锁或者分配了一些内存块的线程,或者应该生成一些其他线程正在等待的事件或数据时会发生什么?应用程序的其余逻辑会发生什么?你将永远处于风险之中,小而明显的问题将转化为难以复制和调查的复杂问题。杀死线程是不安全的,因为它可能使您的应用程序处于许多不同的不一致状态。请查看cert.org上链接中的信息。
我没有让中断在Android中工作,所以我使用这个方法,完美地工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds () {
Thread t = new Thread(new CheckUpdates ());
t. start();
}
private class CheckUpdates implements Runnable{
public void run () {
while (shouldCheckUpdates ){
//Thread sleep 3 seconds
System. out. println("Do your thing here");
}
}
}
public void stop (){
shouldCheckUpdates = false;
} |
-
应该将volatile关键字添加到shouldCheckUpdates中,以便编译器使用线程本地存储进行优化。