57

为什么Thread.stop()在 Java 中被弃用?在他们的网站上,我看到以下内容:

为什么被Thread.stop弃用?

因为它本质上是不安全的。停止线程会导致它解锁所有已锁定的监视器。(当ThreadDeath异常向上传播时,监视器被解锁。)如果以前受这些监视器保护的任何对象处于不一致状态,其他线程现在可能会查看这些处于不一致状态的对象。据说这些物体已损坏。当线程对损坏的对象进行操作时,可能会导致任意行为。这种行为可能很微妙且难以检测,也可能很明显。与其他未经检查的异常不同,ThreadDeath静默杀死线程;因此,用户没有警告他的程序可能已损坏。损坏可以在实际损坏发生后的任何时间出现,甚至在未来几小时或几天内。

我不明白他们所说的“监视器”是什么意思。无论如何,我的问题是如果Thread.stop()不应该调用,那么应该如何停止 Java 线程?

4

5 回答 5

53

您问:

我的问题是如果没有办法停止 Java 中的线程,那么如何停止线程?

答案:在 Java 中,没有干净、快速或可靠的方法来停止线程。

线程终止并不是那么简单。一个正在运行的线程,通常被许多作者称为轻量级进程,它有自己的堆栈并且是自己命运的主人(当然守护进程也是如此)。它可能拥有文件和套接字。它可能持有锁。突然终止并不总是那么容易:如果线程正在写入文件并在完成写入之前被终止,则可能会出现不可预测的后果。或者当它被击中头部时,线程持有的监视器锁怎么办?

相反,线程依赖于一种称为中断的协作机制。这意味着线程只能通知其他线程停止,而不是强制它们停止。

为了停止 Java 中的线程,我们依赖于一种称为中断的协作机制。这个概念很简单。要停止一个线程,我们所能做的就是给它一个信号,也就是中断它,请求线程在下一个可用的机会时自行停止。就这样。不知道接收线程可能对信号做什么:它甚至可能懒得检查信号;甚至更糟的是忽略它。

来源:https ://codeahoy.com/java/How-To-Stop-Threads-Safely/

于 2013-05-12T04:20:01.083 回答
8

When your thread handles interrupts correctly, it should be possible to instantly terminate it with use of ExecutorService interface. According to Oracle documentation, ExecutorService.shutdownNow() method, attempts to stop all actively executing tasks without waiting for their termination. There are however no guarantees beyond best-effort attempts to stop them. Here is some sample code:

class MyThread implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i < 10000000; i++)
            try {
            System.out.println(i + " ThreadID: " + Thread.currentThread().getId());
            if (Thread.interrupted()) 
                    throw new InterruptedException();
            } catch (InterruptedException e) {
                return;
        }   
    }
}

ExecutorService executor = Executors.newFixedThreadPool(3);
            executor.submit(new MyThread());
            executor.submit(new MyThread());
            executor.submit(new MyThread());
            executor.shutdownNow();

Without termination each thread should print message to console 10000000 times. executor.shutdownNow() method instantly stops all three threads.

于 2014-11-11T18:40:59.297 回答
7

正确的方法是使用连接。join 不会过早停止线程的执行,而是等待线程完成执行,然后再移动到下一条语句。

Thread exampleThread = new Thread(){
    public void run(){
        try {

            Thread.sleep(2000);

        } catch (InterruptedException ex) {
            //handle the exception
        }
    }
};

exampleThread.start();
exampleThread.join();

这里 exampleThread.join() 将等到 exampleThread 完成执行,然后再转到下一条语句。然而,确保线程完成执行的责任在于程序员。从本质上讲,没有办法停止线程,但如果设计正确,则不需要停止线程。

于 2013-05-12T04:23:57.943 回答
3

来自https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html

停止的大多数用法应该由简单地修改一些变量以指示目标线程应该停止运行的代码替换。目标线程应该定期检查这个变量,如果变量指示它要停止运行,则以有序的方式从它的run方法返回。为了确保停止请求的及时通信,变量必须是易失的(或者对变量的访问必须是同步的)。

于 2017-07-09T17:48:23.583 回答
2

停止线程的逻辑应该在你的线程实现中处理,这样你就可以确定一切都按照你想要的方式进行。例如,您可以创建一个cancel()更改线程状态的方法,该方法会循环检查。像这样:

class StoppableThread implements Runnable {

    boolean isCancelled = false;


    public void run() {
        while (!isCancelled) {
            System.out.println("Thread is running with all its might!");

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }   
    }


    public void cancel () {
        isCancelled = true;
    }
}
于 2020-02-11T10:54:04.553 回答