JavaEE多线程基础---wait和notify

文章目录

  • wait和notify
    • 1.wait()方法
    • 2.notify()方法
    • 3.notifyAll()方法
    • 4.sleep和wait的对比
  • 总结


wait和notify

线程很讨厌的一点,抢占式执行
调度的过程是随机的~~
很多时候,我们希望多个线程按照一个预期的顺序来进行执行 ~

wait notify 就是来调配线程执行顺序的~

线程执行到wait,就会发生阻塞~~
直到另一个线程,调用notify 把这个wait唤醒~ 才会继续往下走~

监视器,此处特指的是 synchronized ~ synchronized 也叫做监视器锁

1.wait()方法

wait操作,内部本质上,做了三件事 :

1.释放当前锁(保证其他线程能够正常往下运行)~
2.进行等待通知
3.满足一定条件的时候(别人调用notify),被唤醒,然后尝试重新获取锁

等待通知的前提是要先释放锁,而释放锁的前提,是你得加了锁(加上锁,才能谈释放)
脱离 synchronized 使用 wait 会直接抛出异常!

wait 结束等待的条件:

  • 其他线程调用该对象的 notify 方法.
  • wait 等待时间超时 ( wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
  • 其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.

观察wait()方法使用:
JavaEE多线程基础---wait和notify_第1张图片
因为没有调用notify(),所以线程一直处于阻塞状态~

在这里插入图片描述

2.notify()方法

notify 方 法 是 唤 醒 等 待 的 线 程 ❕

JavaEE多线程基础---wait和notify_第2张图片

  • 方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知,并使它们重新获取该对象的对象锁。
  • 如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 “先来后到”)
  • notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

观察notify()方法使用:

  public static void main(String[] args) {
        Object object = new Object();
        Thread thread = new Thread(()-> {
            synchronized (object) {
                System.out.println("wait之前");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("wait 之后");
            }
        });

        Thread thread1 = new Thread(()-> {
            synchronized (object) {
                System.out.println("notify 之前");
                object.notify();
                System.out.println("notify 之后");
            }
        });

        thread.start();
        thread1.start();

    }

JavaEE多线程基础---wait和notify_第3张图片
要保证加锁的对象和调用wait的对象得是同一个对象,还要保证,调用的wait对象和调用notify的对象也是同一个对象~~

a.wait();
b.notify()

上述代码是无法唤醒await的!!!

如果线程1先调用了wait,线程2后调用notify,此时notify会唤醒wait
如果线程2先调用了notify,线程1后执行了wait,此时就会错过唤醒wait !(但如果没人wait,调用notify()没有副作用)

❗ 所以编写代码的时候要考虑notify是否会在wait之前执行的情况,防止wait没人唤醒,导致一直等待~

wait/notify 控制多线程之间的执行先后顺序~
总结:

  1. 都要搭配synchronized来进行使用
  2. 得使用同一个对象,才是有效的
  3. 用来加锁的对象和wait / notify对象也得一致
  4. 即使当前没有线程在wait,直接notify也不会有副作用

在这里插入图片描述

3.notifyAll()方法

多个线程都在wait的话,notify是随机唤醒一个~
notifyAll则是全部唤醒!!
但很少用到~
因为即使唤醒了所有的wait,这些wait又需要重新竞争锁,重新竞争锁的过程仍然是单行的~~

JavaEE多线程基础---wait和notify_第4张图片

4.sleep和wait的对比

都是让线程进入阻塞等待的状态
sleep是通过时间来控制何时唤醒的~~
wait则是由其他线程通过notify来唤醒的~

wait还有一个重载版本,参数可以传时间,表示等待的最大时间(类似于join)

总结

在这里插入图片描述

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!

你可能感兴趣的:(java,算法,面试)