线程:java中的notify()和wait()

时间:2017-02-06 06:58:57

标签: java multithreading

我有一个简单的代码片:

public class ThreadA {
public static void main(String[] args){
    ThreadB b = new ThreadB();
    b.start();

    synchronized(b){
        try{
            System.out.println("Waiting for b to complete...");
            b.wait();
        }catch(InterruptedException e){
            e.printStackTrace();
        }

        System.out.println("Total is: " + b.total);
    }
}



class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

结果:

Waiting for b to complete...
Total is: 4950

我有一个问题,为什么我们需要使用这个代码,我不清楚这里。

 synchronized(this){
        for(int i=0; i<100 ; i++){
            total += i;
        }
        notify();
    }

当我在这里使用synchronized时,我的结果相同。

2 个答案:

答案 0 :(得分:1)

notify()被调用且相应的wait()看到时,&#34;发生之前&#34}建立关系:ThreadB之前notify()中发生的所有事件将在相应的ThreadA返回后在wait()中显示。因此,在您的情况下,total的所有修改都会在notify()之前完成,并且可以安全地假设ThreadA会看到这些更改。

但请注意,使用wait() / notify()进行同步的方式不正确。可能存在虚假的唤醒(即wait()在没有相应的notify()的情况下醒来。有一些特定的惯用方法来使用这些方法(它们实际上是伪装的POSIX条件变量)。其中之一是定义一个&#34;条件&#34;可以从两个主题中检查(例如&#34; is_completed变量为true)并在循环中调用wait(),请参阅here

答案 1 :(得分:0)

当线程终止时,它会调用this.notifyAll(),因此您在notify()中对ThreadB的调用并非绝对必要。

但是,作为Thread.join()注释的文档,不建议在Thread对象上使用监视操作:

  

当线程终止时,将调用this.notifyAll方法。建议应用程序不要在wait个实例上使用notifynotifyAllThread

如果您想等待ThreadB完成,只需从b.join()拨打ThreadA即可。您不需要任何同步块:

public class ThreadA {
    public static void main(String[] args) throws InterruptedException {
        ThreadB b = new ThreadB();
        b.start();
        System.out.println("Waiting for b to complete...");
        b.join();
        System.out.println("Total is: " + b.total);
    }
}

public class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
    }
}