是否有一种强制停止Java线程的好方法?

时间:2011-03-09 05:40:09

标签: java multithreading

我想立即停止Java线程但是当我尝试线程时总是需要一些时间才能停止。 是否有一种强制Java线程立即停止的好方法?

7 个答案:

答案 0 :(得分:16)

没有好办法立即停止线程。

  • Thread.stop(),但它很危险并已弃用。不要使用它,除非:

    1. 您完全理解这些问题,

    2. 彻底分析了您的代码,并确定问题不适用和/或风险可以接受。

  • Thread.interrupt(),但无法保证线程会快速停止,甚至根本不会停止。该行为将取决于应用程序线程代码是否已设计为通知并正确响应中断。

  • 有一种方法是写线程来定期检查一个标志,但是如果不经常检查标志(偶然或设计),则线程不会很快停止。

    < / LI>

FWIW,旗帜和interrupt()方法基本相同。在这两种情况下,期望被中断的线程需要定期检查;例如通过调用interrupted()isInterrupted()或检查标志。

这些方法之间的区别在于,当代码等待interrupt()或在I / O操作中被阻止时,notify()机制将起作用。因此,并且因为interrupt是一种独立于应用程序的接受方式,所以通常优先考虑特定于应用程序的flag机制。

答案 1 :(得分:6)

无法使用Thread.Interrupt停止正在运行的线程,只能使用Thread.Interrupt停止等待或阻塞线程。但是使用共享变量来表示它应该停止正在执行的操作。线程应该定期检查变量,(例如:使用while循环)并以有序的方式退出。

private boolean isExit= false;

public void beforeExit() {
    isExit= true;
}

public void run() {
    while (!isExit) {

    }
}

答案 2 :(得分:6)

有一种很好的方法可以安全地(并且很快)强制停止一个线程:

System.exit(0)

不幸的是,这有杀死所有其他线程的副作用

答案 3 :(得分:2)

在任何情况下都不要使用Thread.stop - 如果你问这个问题,那么你就不能理解Java线程模型足以安全地使用它了。

好奇的细节在这里:Java Thread Primitive Deprecation

如果你真的擅长Java并发,那么你就会明白为什么你永远不应该使用它,即使它在你自己的代码中完全安全,它也会使你的代码受到污染而且无法使用还有谁。相反,你最终可能会使用布尔变量技巧或其他一些模式来告诉线程何时应该完成然后退出。

不要使用Thread.stop。永远。

答案 4 :(得分:1)

你的线程可以放在while循环中,每次检查一个布尔变量。当您将变量设置为false时,循环将结束,线程也将结束。要在通过当前循环之前结束线程,可以使用break关键字。

这可以避免使用诸如Thread.stop()之类的弃用方法。

private boolean run = true;

//Call this method to end your thread
void stopRunning(){
    run = false;
}

//This loop would go into the overided run() method

while(run){
    //Put your task here
}

线程将完成当前任务,然后自然停止。

如果在完成任务之前需要停止线程,可以使用循环中的if / else检查运行变量,并像其他任何地方一样结束线程。

while(run){
    //Your code here

    /*Be sure your not stopping the task at a point that will harm your program.*/
    if(!run){break;}
}

答案 5 :(得分:0)

即使在 JDK 的更高版本中,您仍然可以停止具有特定异常的线程。

您需要使用反射,因为 stop(Throwable) 已被移除,但底层本机方法 stop0(Throwable)(也由 stop() 调用)仍然存在,尽管不可见。

这是一个简单的方法,可用于通过抛出给定的异常来主动停止线程。

public static boolean stopWith(Thread t, Throwable e){
    try {
        Method m = Thread.class.getDeclaredMethod("stop0", Object.class);
        m.setAccessible(true);
        m.invoke(t, e);
        m.setAccessible(false);
        return true;
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    return false;
}

这适用于 JDK 11,但 is 代表和 illegal reflective access

如果您的代码使用模块,默认情况下您的模块不允许通过反射访问非公共成员(因为 java.base/java.lang 不对其他模块开放)。因此会抛出 java.lang.reflect.InaccessibleObjectException。 可以使用 JVM 的 java.base/ 标志 --add-opens 模块的 override the default opening, 例如--add-opens java.base/java.lang=your.module.

如果您的代码未使用模块(即 Java 8 或之前版本),由于向后兼容 java.base/ 对所有未命名的模块 (ALL-UNNAMED) 开放,因此不会引发异常。 但是记录了一条不可避免的警告消息:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by YourCalss (file:/path/to/your/class/) to method java.lang.Thread.stop0(java.lang.Object)
WARNING: Please consider reporting this to the maintainers of TestSop
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

答案 6 :(得分:0)

在任何语言中,您都不能编写依赖于执行模式或任何其他进程或线程的时间的代码。你可以发送一个信号要求一个线程停止它自己,或者你可以强行终止它,但是你仍然不能准确地预测什么时候会完成这个肮脏的事情。您必须仔细编写不受所谓“竞争条件”影响的代码。