Thread.stop() - 已弃用

时间:2013-05-12 04:16:13

标签: java multithreading

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

  

为什么Thread.stop已被弃用?

     

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

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

5 个答案:

答案 0 :(得分:38)

你问:

  

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

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

  

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

相反,Threads依赖于名为 Interruption 合作机制。这意味着线程只能信号其他线程停止,而不是强制它们停止。

  

要在Java中停止线程,我们依赖于一个名为Interruption的合作机制。这个概念很简单。要停止一个线程,我们所能做的只是传递一个信号,即中断它,请求线程在下一个可用的机会停止。就这样。没有人知道接收器线程可能对信号做了什么:它甚至可能不会检查信号;或者更糟糕的是忽略它。

来源:http://10kloc.wordpress.com/2013/03/03/java-multithreading-steeplechase-stopping-threads/

答案 1 :(得分:8)

正确的方法是使用联接。而不是过早地停止线程的执行,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完成执行,然后再转到下一个语句。但是,确保线程完成执行的责任在于程序员。 本质上,没有办法阻止一个线程,但如果你设计正确,你就不需要停止线程了。

答案 2 :(得分:7)

当您的线程正确处理中断时,应该可以使用ExecutorService接口立即终止它。根据Oracle文档ExecutorService.shutdownNow()方法,尝试在不等待终止的情况下停止所有正在执行的任务。但是,除了尽力而为之外,没有任何保证可以阻止它们。以下是一些示例代码:

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

没有终止,每个线程应该向控制台打印消息10000000次。 executor.shutdownNow()方法立即停止所有三个线程。

答案 3 :(得分:3)

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

  

stop的大多数用法应该由代码修改,该代码只是修改某个变量以指示目标线程应该停止运行。目标线程应该定期检查此变量,并且如果变量指示它将停止运行,则以有序的方式从其run方法返回。为了确保快速通信停止请求,变量必须是易失性的(或者必须同步对变量的访问)   )。

答案 4 :(得分:1)

停止线程的逻辑应该在线程的实现中处理,以便确保一切都按您希望的方式进行。 例如,您可以创建一个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;
    }
}