java notify()不是只能唤醒单个线程么,为什么我程序的notify()能唤醒3个

程序是这样的

/*   第一个类*/
 public class ThreadB extends Thread{
    int total;
    public void run(){
        synchronized(this){
            for(int i=0;i<101;i++){
                total+=i;
            }
            try {
                sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            notify();
        }
    }
    public int getTotal(){
        return this.total;
    }

}



/*   第二个类*/
public class ReaderResult extends Thread{
    ThreadB c;
    public ReaderResult(ThreadB c){
        this.c=c;
    }
    public void run(){
        synchronized (c) {
            try{
                System.out.println(Thread.currentThread()+"等待计算结果。。。。");
                c.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread()+"计算结果为:"+c.getTotal());
        }
    }
    public static void main(String[] args) {
        ThreadB calculator = new ThreadB();

        ReaderResult reader1=new ReaderResult(calculator);      
        ReaderResult reader2=new ReaderResult(calculator);
        ReaderResult reader3=new ReaderResult(calculator);
        reader1.start();
        reader2.start();
        reader3.start();
        calculator.start();


    }
}

输出结果大多数都
Thread[Thread-1,5,main]等待计算结果。。。。
Thread[Thread-3,5,main]等待计算结果。。。。
Thread[Thread-2,5,main]等待计算结果。。。。
Thread[Thread-1,5,main]计算结果为:5050
Thread[Thread-2,5,main]计算结果为:5050
Thread[Thread-3,5,main]计算结果为:5050

理论上不是只能唤醒一个吗?

3个回答

notify是只能唤醒一个线程没错,但是你应该看清楚解释,当线程被wait时要有个对象,或者锁去调用这个方法,同理notify时,也是这样。而且notify的调用对象是调用wait方法时的对象,它会从等待队列中将其唤醒。你注意代码,你三个线程调用wait方法的对象是同一个对象,那么应该会导致一次notify唤醒三个。

你这三个wait中锁的对象是三个不同的对象,这三个虽然他们有相同的名字但是却是三个不同的ReaderResult类中的,而且你再唤醒的时候也是在他们本身内部唤醒,根据以上两点,导致你的notify唤醒没有达到预想结果。可以尝试将 ThreadB c;换成static而且将notify函数放在单独一个线程而不是在他们被wait的线程中。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问