• Java中的wait和notify方法


    目录

    一、前言

    二、wait()方法

    1、wait()方法要做的事

    2、结束等待的方式

    三、notify()方法

    四、wait()和sleep()的对比


    一、前言

            由于线程之间是抢占式执行的,我们不能确定线程的调度顺序,而有时候我们又希望多个线程之间可以有序地协调调度,于是就有了wait()notify()方法。

            wait()notify()方法都是Object类中的方法,所以我们可以通过任意的对象来调用这些方法。

    二、wait()方法

    1、wait()方法要做的事

    wait()方法表面上看起来只是让线程进入了等待的状态,实际上它要做三件事情:

    (1) 释放当前的锁(所以调用wait()方法之前需要先加锁,即配合synchronized关键字使用);

    (2) 使当前执行代码的线程进行等待;

    (3) 满足一定条件时被唤醒(其他线程中调用了该对象的notify()方法),尝试重新获取锁。

    注意:调用wait()方法的对象必须和synchronized的锁对象是同一个对象。

    2、结束等待的方式

    (1) 其他线程中调用了该对象的notify()方法;

    (2) 如果调用的是带参数的wait()方法(可以传入参数来指定等待的时间),等待时间结束即可;

    (3) 其他线程中调用该等待线程的interrupted()方法,提前唤醒该等待线程,同时也会抛出InterruptedException异常。

    1. public class Test3 {
    2. public static void main(String[] args) throws InterruptedException {
    3. Thread t1 = new Thread(() -> {
    4. synchronized (Test3.class) {
    5. try {
    6. //t1线程进入wait状态
    7. //锁对象和调用wait方法的对象必须是同一个
    8. Test3.class.wait();
    9. } catch (InterruptedException e) {
    10. e.printStackTrace();
    11. }
    12. }
    13. System.out.println("t1线程结束");
    14. });
    15. t1.start();
    16. //t1线程启动后休眠1秒
    17. Thread.sleep(1000);
    18. Thread t2 = new Thread(() -> {
    19. t1.isInterrupted();
    20. System.out.println("t2线程中设置标志位");
    21. t1.interrupt();
    22. });
    23. t2.start();
    24. }
    25. }

    注意:调用wait()方法和notify()方法的对象必须是同一个,否则无法唤醒线程。

    三、notify()方法

            notify()方法是用来唤醒调用wait()方法后进入等待的线程,但是调用两个方法的对象必须是同一个对象,如果在线程1中通过A对象调用wait(),而在线程2中通过B对象调用notify(),则无法唤醒A对象所在的线程。

    注意:

    (1) 如果多个线程中都通过对象A都调用了wait(),那么另外一个线程中通过对象A调用notify(),只会随机唤醒其中一个线程;要想唤醒所有线程,需要调用notifyAll()方法。

    (2) 如果线程2先调用notify(),线程1再调用wait(),则线程1会一直等待,无法被唤醒。

    代码示例:在t2线程中调用notify()唤醒调用了wait()t1线程

    1. public class Test4 {
    2. public static void main(String[] args) throws InterruptedException {
    3. Object object = new Object();
    4. Thread t1 = new Thread(() -> {
    5. synchronized (object){
    6. System.out.println("调用wait之前");
    7. try {
    8. object.wait();
    9. } catch (InterruptedException e) {
    10. e.printStackTrace();
    11. }
    12. System.out.println("调用wait之后");
    13. }
    14. });
    15. t1.start();
    16. //t1线程启动后休眠100毫秒,保证先执行t1再执行t2
    17. Thread.sleep(100);
    18. Thread t2 = new Thread(() -> {
    19. synchronized (object){
    20. System.out.println("调用notify之前");
    21. object.notify();
    22. System.out.println("调用notify之后");
    23. }
    24. });
    25. t2.start();
    26. }
    27. }

    代码运行结果:

    四、wait()和sleep()的对比

    相同点:都可以让线程放弃执行一段时间。

    不同点:

    (1) wait()是用于线程间通信的,sleep()是让线程阻塞一段时间;

    (2) wait()需要搭配synchronized使用,sleep()不需要;

    (3) wait()Object类的成员方法,sleep()Thread类的静态方法。

  • 相关阅读:
    HTML5七夕情人节表白网页制作【花瓣图片表白】HTML+CSS+JavaScript html生日快乐祝福网页制作
    软考-信息安全工程师-2
    艾泊宇产品战略:技术型老板必须警惕的2个致命错误
    048-第三代软件开发-数据回放
    CV攻城狮入门VIT(vision transformer)之旅——近年超火的Transformer你再不了解就晚了!
    网络流——Dinic算法求最大流
    redis集群搭建教程及遇到的问题处理
    浏览器存储
    mysql主从复制和读写分离
    A*算法例子
  • 原文地址:https://blog.csdn.net/m0_67683346/article/details/126868916