【Java|多线程与高并发】wait和notify方法详解

1.前言

在Java多线程环境中,线程之间是抢占式执行的,线程的调度是随机的.这就很难受了. 在很多情况下我们希望线程以我们想要的顺序来执行. 这就需要waitnotify这两个方法

在这里插入图片描述

2.wait和notify的基本使用

首先是wait方法
在这里插入图片描述
wait是Object类的方法,而Java中的类都是间接或直接继承于Object类. 因此只要是类的实例都可以调用wait方法

运行上述代码:
在这里插入图片描述
可以看到这里抛出了一个 非法的锁状态异常

其实wait方法的执行分为三步:

  1. 释放当前锁
  2. 进行等待通知
  3. 满足一定的条件(其它线程调用notify),被唤醒,然后重新获取锁

什么要先释放锁,再进行等待通知呢?

因为wait如果不释放锁,可能会影响到其它线程的执行,就是为了保证不影响其它线程的执行

因此wait与锁密不可分
在这里插入图片描述
对上述代码进行加锁,就不会抛出异常了.

但上述代码的执行并没有结束,因为线程在调用wait方法之后,会一直处于阻塞状态,直到有其它线程调用notify方法为止.
而调用notify方法的线程要和调用wait方法的线程是针对同一个对象进行加锁的才行.

示例:

    public static void main(String[] args) {
    
    
        Object object = new Object();
        Thread t1 = new Thread(() ->{
    
    
            while(true){
    
    
                synchronized (object){
    
    
                    System.out.println("wait 之前");
                    try {
    
    
                        object.wait();
                    } catch (InterruptedException e) {
    
    
                        throw new RuntimeException(e);
                    }
                    System.out.println("wait 之后");
                }
            }
        });
        t1.start();
        Thread t2 = new Thread(() ->{
    
    
            while(true){
    
    
                synchronized (object){
    
    
                    System.out.println("notify 之前");
                    object.notify();
                    System.out.println("notify 之后");
                }
                try {
    
    
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
    
    
                    throw new RuntimeException(e);
                }
            }
        });
        t2.start();
    }

运行截图:
在这里插入图片描述
上述标注的是一组 waitnotify方法的执行流程.

注: 如果先调用的是notify方法,代码并不会有什么影响.

3. notifyAll方法

Java中除了使用notify方法唤醒线程,还有一个notifyAll方法.
当一个线程调用了某个对象的notifyAll方法后,该对象上的所有等待线程将被唤醒,即使唤醒了所有在等待的线程,这些线程之间也要进行锁竞争(串行执行)。

4. wait和sleep方法的对比

wait方法和sleep方法的对比也是面试中经常会问到的问题

对于这个问题,可以从相同点和不同点进行回答:

相同点: 都是让线程进入阻塞等待状态
不同点:sleep方法是通过时间来通知唤醒,而wait方法则需要使用notify或notifyAll进行唤醒

5. 总结

waitnotify方法用于实现线程间的协作和通信.
wait方法使线程进入等待状态,notify方法唤醒一个等待线程,notifyAll方法唤醒所有等待线程。
通过上述三个方法,可以使线程按照特定的顺序执行或者等待某个条件满足后再执行。

在这里插入图片描述

感谢你的观看!希望这篇文章能帮到你!
专栏: 《从零开始的Java学习之旅》在不断更新中,欢迎订阅!
“愿与君共勉,携手共进!”
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_63463510/article/details/131326566