Java notify()在wait()之前运行? [英] Java notify() run before wait()?

查看:122
本文介绍了Java notify()在wait()之前运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

如上例所示,如果 wait()阻止先输入,ThreadB中的后续 notify()将告诉主线程继续。

As the example above, if wait() block enter first, the subsequent notify() in ThreadB will tell the Main Thread to continue.

但我们不能保证 wait()将在 notify(),如果ThreadB首先进入块怎么办? Notify()将在 wait()之前执行,所以 wait()将永远挂在那里(因为没有更多 notify()告诉它继续)?什么通常是处理这个的正确方法?

But we cannot guarantee wait() will execute before notify(), what if ThreadB enter the block first? Notify() will execute before wait(), so wait() will hang there forever (because no more notify() to tell it to continue)? What usually is the proper way to handle this?

推荐答案

你应该几乎总是有一个谓词和wait / notify。也就是说,你需要一个可以检查的条件
,例如变量变为真,队列变空/满等等。只是盲目地等待某人调用.notify()只有很少的用例。

You should almost always have a predicate together with wait/notify. That is, you need a condition that you can check, such as a variable becoming true, a queue becoming empty/full etc. Just blindly waiting for someone to call .notify() have very few use cases.

所以,以下是不行的,因为你说的原因,另一个线程可以在ThreadA调用之前调用.notify()。等于()

So, The following is Not OK, for the reason you say, the other thread could call .notify() before ThreadA calls .wait()

public class ThreadA {
    public static Object latch = new Object();
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized(latch ) {
            latch.wait(); //wait for B to finish a calculation
        }
        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
       synchronized(ThreadA.latch) {
           ThreadA.latch.notify();
       }
    }
}

你需要做类似的事情这个:

You need to do something like this:

 public class ThreadA {
    public static Object latch = new Object();
    public static boolean done = false;
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized(latch ) {
            while (!done) {   //wait for B to indicate it is finished.
                latch.wait(); 
            }
        }
        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
       synchronized(ThreadA.latch) {
           ThreadA.done = true;         
           ThreadA.latch.notify();
       }
    }
}

请注意,在上面, done 变量受同步块保护, .wait()将自动释放/重新获取该锁定。所以没有竞争条件,如果在我们到达 .wait()之前调用.notify(),ThreadA会发现因为完成 true ,并且根本不输入 .wait()

Note that in the above, the done variable is protected by the synchronized block, .wait() will atomically release/re-aquire that lock. So there is no race condition, and if .notify() is called before we get to the .wait() call , ThreadA will discover that because done will be true and not enter the .wait() call at all.

对于一个简单的例如此代码的情况,你可以等待ThreadB结束,可以用 b.join();

For a simple case such as this code, you can just wait for ThreadB to to end, can be done with b.join();

这篇关于Java notify()在wait()之前运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆