线程停止和同步

时间:2011-01-25 14:49:15

标签: java thread-safety volatile

我正在读一本书,上面写着不使用这样的代码:

private volatile Thread myThread;

....

myThread.stop();

相反应该使用:

if (myThread != null ) {

 Thread dummy = myThread;

 myThread = null;

 dummy.interrupt();


}

不幸的是,这个主题还没有详细说明......有人可以解释一下吗?

7 个答案:

答案 0 :(得分:3)

您可以找到一个很好的答案,说明为什么不使用stop()方法here。您可以使用此变量保存布尔变量并无限循环,而不是使用此方法:

public class MyRunnable extends Runnable {
    public volatile boolean keepRunning = true;
    public void run() {
        while (keepRunning) {
            ... // do what you have to do
        }
    }
}

一旦决定完成,您只需将keepRunning变量设置为false即可。然后你的线程将:   - 完成剩下的步骤   - 终止

就像你以受控方式完成工作而不使用不安全的stop()方法。

答案 1 :(得分:3)

stop()已弃用。永远不要永远不要使用stop()。您可以改为使用java concurrency

来自Javadoc

  

这种方法本质上是不安全的。使用Thread.stop停止一个线程会导致它解锁它已锁定的所有监视器(这是未经检查的ThreadDeath异常向上传播的自然结果)。如果先前受这些监视器保护的任何对象处于不一致状态,则受损对象对其他线程可见,可能导致任意行为。 stop的许多用法应该被简单修改某个变量的代码替换,以指示目标线程应该停止运行。目标线程应该定期检查此变量,并且如果变量指示它将停止运行,则以有序的方式从其run方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。

查看Java Concurrency in Practice第7章(取消和关闭)

答案 2 :(得分:1)

Thread.stop()deprecated。不要使用它。为什么?阅读Java Thread Primitive Deprecation

答案 3 :(得分:1)

不推荐使用Thread.stop,不应使用它(更多信息here)。

示例代码似乎使对“myThread”的引用无效,然后发出信号让它中断。假设“myThread”是对你的线程的唯一引用,并且线程中运行的代码正确处理中断请求(而不是忽略它们),当“if(myThread!= null)”时,线程将结束并有资格进行垃圾回收。 “代码块完成。

答案 4 :(得分:1)

尽管不推荐使用Thread.stop。知道使用Thread.stop可以绕过copmiler检查的异常控制也很有用。例如,

public void doSomething(){
    Thread.currentThread().stop(new IOException());
}

这将抛出IOException。 IOException是一个经过检查的已检查异常,编译器通常会强制客户端捕获或让方法抛出它。这里doSomething抛出一个未经检查的IOException

答案 5 :(得分:1)

每个人都提供了很好的信息,说明为什么不调用Thread.stop()。

谢尔盖的评论修正了我给出的关于interrupt()处理的错误信息。我更喜欢使用信号标志,就像lewap的答案一样。就像谢尔盖所说的那样,interrupt()是为了唤醒一个被阻塞操作的线程。如果你的线程没有调用任何阻塞操作,那么interrupt()实际上不会终止该线程。你的线程虽然可以调用isInterrupted()来查看是否已经调用了中断(基本上是一个信号标志)。

回到你的书的例子,我不喜欢它。

if (myThread != null ) {

    Thread dummy = myThread;

    myThread = null;

    dummy.interrupt();

}

在此示例中,没有充分的理由复制到虚拟变量。你很困惑。

本书作者可能正在考虑尝试阻止其他线程同时尝试中断同一个线程,但是中断代码不是线程安全的(“检查是否为null并设置为null”操作不是原子的),所以编写虚拟任务是在不增加实际线程安全性的情况下弄脏水域。

答案 6 :(得分:1)

除了@Paweloque建议的内容(这是一种完美的方式)之外,还有另一种方法可以使用stop()建议here

错误的方式:

假设您的applet包含以下启动,停止和运行方法:

private Thread blinker;

public void start() {
    blinker = new Thread(this);
    blinker.start();
}

public void stop() {
    blinker.stop();  // UNSAFE!
}

public void run() {
    Thread thisThread = Thread.currentThread();
    while (true) {
        try {
            thisThread.sleep(interval);
        } catch (InterruptedException e){
        }
        repaint();
    }
}

正确的方式

您可以通过将applet的stop和run方法替换为以下内容来避免使用Thread.stop:     private volatile Thread blinker;

public void stop() {
    blinker = null;
}

public void run() {
    Thread thisThread = Thread.currentThread();
    while (blinker == thisThread) {
        try {
            thisThread.sleep(interval);
        } catch (InterruptedException e){
        }
        repaint();
    }
}