你如何在 Java 中杀死一个线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/671049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:41:26  来源:igfitidea点击:

How do you kill a Thread in Java?

javamultithreadinginterrupt

提问by flybywire

How do you kill a java.lang.Threadin Java?

你如何java.lang.Thread在Java中杀死a ?

采纳答案by JaredPar

See this thread by Sun on why they deprecated Thread.stop(). It goes into detail about why this was a bad method and what should be done to safely stop threads in general.

请参阅Sun 的Thread.stop()主题,了解他们为何弃用。它详细说明了为什么这是一个糟糕的方法,以及通常应该采取什么措施来安全地停止线程。

The way they recommend is to use a shared variable as a flag which asks the background thread to stop. This variable can then be set by a different object requesting the thread terminate.

他们推荐的方法是使用共享变量作为要求后台线程停止的标志。然后可以由请求线程终止的不同对象设置此变量。

回答by Fredrik

Generally you don't..

一般你不会..

You ask it to interrupt whatever it is doing using Thread.interrupt() (javadoc link)

您要求它使用Thread.interrupt() (javadoc 链接)中断正在执行的任何操作

A good explanation of why is in the javadoc here (java technote link)

此处的 javadoc 中很好地解释了原因(java 技术说明链接)

回答by karim79

One way is by setting a class variable and using it as a sentinel.

一种方法是设置一个类变量并将其用作哨兵。

Class Outer {
    public static volatile flag = true;

    Outer() {
        new Test().start();
    }
    class Test extends Thread {

        public void run() {
            while (Outer.flag) {
                //do stuff here
            }
        }
    }

}

Set an external class variable, i.e. flag = true in the above example. Set it to false to 'kill' the thread.

设置一个外部类变量,即上例中的flag = true。将其设置为 false 以“杀死”线程。

回答by mlohbihler

There is of course the case where you are running some kind of not-completely-trusted code. (I personally have this by allowing uploaded scripts to execute in my Java environment. Yes, there are security alarm bell ringing everywhere, but it's part of the application.) In this unfortunate instance you first of all are merely being hopeful by asking script writers to respect some kind of boolean run/don't-run signal. Your only decent fail safe is to call the stop method on the thread if, say, it runs longer than some timeout.

当然,也有您正在运行某种不完全受信任的代码的情况。(我个人通过允许上传的脚本在我的 Java 环境中执行来实现这一点。是的,到处都在响起安全警报,但它是应用程序的一部分。)在这个不幸的例子中,首先你只是通过询问脚本编写者来抱有希望尊重某种布尔运行/不运行信号。你唯一体面的故障安全是在线程上调用 stop 方法,如果它运行时间超过某个超时。

But, this is just "decent", and not absolute, because the code could catch the ThreadDeath error (or whatever exception you explicitly throw), and not rethrow it like a gentlemanly thread is supposed to do. So, the bottom line is AFAIA there is no absolute fail safe.

但是,这只是“体面的”,而不是绝对的,因为代码可以捕获 ThreadDeath 错误(或您明确抛出的任何异常),而不是像绅士线程应该做的那样重新抛出它。所以,底线是 AFAIA 没有绝对的故障安全。

回答by Konrad Reiche

In Java threads are not killed, but the stopping of a thread is done in a cooperative way. The thread is asked to terminate and the thread can then shutdown gracefully.

在 Java 中,线程不会被杀死,但线程的停止是以协作方式完成的。线程被要求终止,然后线程可以正常关闭。

Often a volatile booleanfield is used which the thread periodically checks and terminates when it is set to the corresponding value.

通常使用一个volatile boolean字段,当它被设置为相应的值时,线程会定期检查并终止该字段。

I would notuse a booleanto check whether the thread should terminate. If you use volatileas a field modifier, this will work reliable, but if your code becomes more complex, for instead uses other blocking methods inside the whileloop, it might happen, that your code will not terminateat all or at least takes longeras you might want.

不会使用 aboolean来检查线程是否应该终止。如果您使用volatile的场调节剂,这将工作可靠,但如果你的代码变得更加复杂,对于而是使用内的其他阻止方法while循环,它可能发生,你的代码将不会终止所有或至少需要更长的时间,你可能想要。

Certain blocking library methods support interruption.

某些阻塞库方法支持中断。

Every thread has already a boolean flag interrupted statusand you should make use of it. It can be implemented like this:

每个线程都有一个布尔标志中断状态,您应该使用它。它可以这样实现:

public void run() {
   try {
      while (!interrupted()) {
         // ...
      }
   } catch (InterruptedException consumed)
      /* Allow thread to exit */
   }
}

public void cancel() { interrupt(); }

Source code adapted from Java Concurrency in Practice. Since the cancel()method is public you can let another thread invoke this method as you wanted.

源代码改编自Java Concurrency in Practice。由于该cancel()方法是公共的,您可以根据需要让另一个线程调用此方法。

回答by Jesse Glick

The question is rather vague. If you meant “how do I write a program so that a thread stops running when I want it to”, then various other responses should be helpful. But if you meant “I have an emergency with a server I cannot restart right now and I just need a particular thread to die, come what may”, then you need an intervention tool to match monitoring tools like jstack.

这个问题比较含糊。如果您的意思是“我如何编写程序以便线程在我想要的时候停止运行”,那么其他各种回答应该会有所帮助。但是,如果您的意思是“我的服务器出现紧急情况,我现在无法重新启动,我只需要一个特定的线程死掉,不管怎样”,那么您需要一个干预工具来匹配诸如jstack.

For this purpose I created jkillthread. See its instructions for usage.

为此,我创建了jkillthread。请参阅其使用说明。

回答by VadimPlatonov

There is a way how you can do it. But if you had to use it, either you are a bad programmer or you are using a code written by bad programmers. So, you should think about stopping being a bad programmer or stopping using this bad code. This solution is only for situations when THERE IS NO OTHER WAY.

有一种方法可以做到。但是如果你不得不使用它,要么你是一个糟糕的程序员,要么你使用的是由糟糕的程序员编写的代码。所以,你应该考虑停止成为一个糟糕的程序员或停止使用这些糟糕的代码。此解决方案仅适用于没有其他方法的情况。

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() );

回答by Anand Rajasekar

There is no way to gracefully kill a thread.

没有办法优雅地杀死一个线程。

You can try to interrupt the thread, one commons strategy is to use a poison pill to message the thread to stop itself

您可以尝试中断线程,一种公共策略是使用毒丸向线程发送消息以使其自行停止

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”);
            }

    }

}

}

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/

http://anandsekar.github.io/cancel-support-for-threads/

回答by ZarathustrA

Attempts of abrupt thread termination are well-known bad programming practice and evidence of poor application design. All threads in the multithreaded application explicitly and implicitly share the same process state and forced to cooperate with each other to keep it consistent, otherwise your application will be prone to the bugs which will be really hard to diagnose. So, it is a responsibility of developer to provide an assurance of such consistency via careful and clear application design.

尝试突然终止线程是众所周知的不良编程实践和糟糕的应用程序设计的证据。多线程应用程序中的所有线程显式和隐式共享相同的进程状态并强制相互协作以保持一致,否则您的应用程序将容易出现很难诊断的错误。因此,开发人员有责任通过仔细和清晰的应用程序设计来保证这种一致性。

There are two main right solutions for the controlled threads terminations:

受控线程终止有两种主要的正确解决方案:

  • Use of the shared volatile flag
  • Use of the pair of Thread.interrupt() and Thread.interrupted() methods.
  • 使用共享的 volatile 标志
  • 使用 Thread.interrupt() 和 Thread.interrupted() 方法对。

Good and detailed explanation of the issues related to the abrupt threads termination as well as examples of wrong and right solutions for the controlled threads termination can be found here:

可以在此处找到与突然线程终止相关的问题的详细说明以及受控线程终止的错误和正确解决方案示例:

https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads

https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads

回答by Steve11235

I want to add several observations, based on the comments that have accumulated.

我想根据积累的评论添加一些观察结果。

  1. Thread.stop()will stop a thread if the security manager allows it.
  2. Thread.stop()is dangerous. Having said that, if you are working in a JEE environment and you have no control over the code being called, it may be necessary; see Why is Thread.stop deprecated?
  3. You should never stop stop a container worker thread. If you want to run code that tends to hang, (carefully) start a new daemon thread and monitor it, killing if necessary.
  4. stop()creates a new ThreadDeathErrorerror on the callingthread and then throws that error on the targetthread. Therefore, the stack trace is generally worthless.
  5. In JRE 6, stop()checks with the security manager and then calls stop1()that calls stop0(). stop0()is native code.
  6. As of Java 13 Thread.stop()has not been removed (yet), but Thread.stop(Throwable)was removed in Java 11. (mailing list, JDK-8204243)
  1. Thread.stop()如果安全管理器允许,将停止线程。
  2. Thread.stop()是危险的。话虽如此,如果您在 JEE 环境中工作并且您无法控制被调用的代码,则可能有必要;请参阅为什么不推荐使用 Thread.stop?
  3. 您永远不应该停止停止容器工作线程。如果你想运行容易挂起的代码,(小心地)启动一个新的守护线程并监视它,必要时杀死它。
  4. stop()ThreadDeathError调用线程上创建一个新错误,然后在目标线程上抛出该错误。因此,堆栈跟踪通常毫无价值。
  5. 在 JRE 6 中,stop()检查安全管理器,然后stop1()调用stop0(). stop0()是本机代码。
  6. 截至 Java 13Thread.stop()尚未删除(尚未),但Thread.stop(Throwable)已在 Java 11 中删除。(邮件列表JDK-8204243