Java多线程专题-wait()、notify、notifyAll()方法

wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。

  • 这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
  • 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
  • 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
  • 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。

注意:一定要在线程同步中使用,并且是同一个锁的资源

class Res {
    public String userSex;
    public String userName;
    //线程通讯标识
    public boolean flag = false;
}


class IntThrad extends Thread {
    private Res res;

    public IntThrad(Res res) {
        this.res = res;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            synchronized (res) {
                if (res.flag) {
                    try {
                        // 当前线程变为等待,但是可以释放锁
                        res.wait();
                    } catch (Exception e) {

                    }
                }
                if (count == 0) {
                    res.userName = "张三";
                    res.userSex = "男";
                } else {
                    res.userName = "李四";
                    res.userSex = "女";
                }
                count = (count + 1) % 2;
                res.flag = true;
                // 唤醒当前线程
                res.notify();
           }
        }
    }
}




class OutThread extends Thread {
    private Res res;

    public OutThread(Res res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (res) {
                if (!res.flag) {
                    try {
                        res.wait();
                    } catch (Exception e) {
                        // TODO: handle exception
                    }
                }
                System.out.println(res.userName + "--" + res.userSex);
                res.flag = false;
                res.notify();
            }
        }
    }
}



public class ThreaCommun {
    public static void main(String[] args) {
        Res res = new Res();
        IntThrad intThrad = new IntThrad(res);
        OutThread outThread = new OutThread(res);
        intThrad.start();
        outThread.start();
    }
}

notify和notifyAll的区别

当你调用notify时,只有一个等待线程会被唤醒而且它不能保证哪个线程会被唤醒,这取决于线程调度器。

虽然如果你调用notifyAll方法,那么等待该锁的所有线程都会被唤醒,但是在执行剩余的代码之前,所有被唤醒的线程都将争夺锁定,这就是为什么在循环上调用wait,因为如果多个线程被唤醒,那么线程是将获得锁定将首先执行,它可能会重置等待条件,这将迫使后续线程等待。

因此,notify和notifyAll之间的关键区别在于notify()只会随机唤醒一个线程,而notifyAll方法将唤醒所有线程。

何时在Java中使用notify和notifyAll

如果所有线程都在等待相同的条件,并且一次只有一个线程可以从条件变为true,则可以使用notify。

在这种情况下,notify是优于notifyAll 因为唤醒所有线程。因为我们知道只有一个线程会受益而所有其他线程将再次等待,所以调用notifyAll方法只是浪费CPU。

虽然这看起来很合理,但仍有一个警告,即无意中的接收者吞下了关键通知。通过使用notifyAll,我们确保所有收件人都会收到通知

wait与sleep区别​​​​​​​

  • 对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
  • sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
  • 在调用sleep()方法的过程中,线程不会释放对象锁。
  • 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。

 

 

 

 

 

 

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页