• 多线程---wait和notify


    使用场景

    我们都知道线程的调度是“随机的”,但是我们在很多时候都希望多个线程能够按照一个预期的顺序来执行。wait和notify就是用来调配线程执行顺序的。

    使用方法

    	public static void main(String[] args) {
            Object object = new Object();
    
            Thread thread1 = new Thread(() -> {
                while (true){
                    synchronized (object){
                        System.out.println("wait之前");
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //在notify唤醒之后执行
                        System.out.println("wait之后");
                    }
                }
            });
            thread1.start();
    
            Thread thread2 = new Thread(() -> {
                while (true){
                    synchronized (object) {
    
                        System.out.println("notify之前");
                        object.notify();
                        //在wait被唤醒之前执行
                        System.out.println("notify之后");
                    }
    
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread2.start();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    解释:

    1. wait和notify得配合使用,wait用来让线程休眠,程序执行到wait就会进入阻塞状态;notify用来唤醒线程,直到另一个线程唤醒休眠的线程后,原线程才能继续往下走。
    2. 它们俩都得搭配synchronized使用,且在使用之前都必须加锁。因为它们是通过“锁竞争”来调配线程执行顺序的。
    3. 锁对象和调用wait和notify的对象要相同。相同才能识别。
    4. 先调用了notify再调用wait可能会发生死锁,一般都会让notify等待wait被调用到后再执行。因为,调用wait进入阻塞等待状态后,如果没有notify唤醒它,它就会一直阻塞产生死锁。
    5. notify单独使用不会报错,不会有异常。

    原理

    其实,wait操作本质上做了三件事儿:

    1. 释放当前锁
    2. 进行等待通知
    3. 别的线程调用notify被唤醒,然后尝试重新获取锁

    为什么要先释放锁,再等待通知呢

    1. 调用wait的对象、调用notify的对象、锁对象,这三个对象是一个对象。只有wait先释放了锁,别的线程才有可能调用到notify来唤醒它。
    2. 在wait进入阻塞等待状态后,它就不会在执行其他操作了。如果不释放锁,别的线程还想借助这个锁对象来执行别的操作时,别的线程就拿不到锁不能执行。白白浪费了系统资源,降低了整体程序的执行效率,延长执行的时间。

    在这里插入图片描述

    notify VS notifyAll

    notify:如果多个线程都在等待被唤醒,notify是随机唤醒一个。

    notifyAll:如果多个线程都在等待被唤醒,notifyAll是全部唤醒。但是这些线程又会有“锁竞争”,重新竞争锁的过程仍然是串行的。

  • 相关阅读:
    css中的单位
    CSDN每日一练 |『买苹果』『最长回文串』『查找整数』2023-10-20
    【敏捷那些事儿 03期】一文讲透敏捷的“道、法、术、器”
    golang 爬虫修炼04 ---利用正则提取数据
    [附源码]Python计算机毕业设计Django教育企业网站
    高等数学(第七版)同济大学 习题10-2(前10题) 个人解答
    DML相关操作
    pthread_mutex_t互斥量
    HTML学生个人网站作业设计成品 HTML+CSS肖战明星人物介绍网页 web结课作业的源码
    11-15 周三 softmax 回归学习
  • 原文地址:https://blog.csdn.net/weixin_62976968/article/details/134088451