wait()和notify()详解

Java多线程基础-7:wait() notify() 用法解析 详解Java多线程编程中,wait()notify()方法的使用方式注意事项,配合代码案例~ 阅读详情

等待通知机制基本用法:

public class Test {

    public static void main(String[] args) throws InterruptedException {

        Thread waitThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Test.class){
                    System.out.println(Thread.currentThread().getName() + " is holding lock...");
                    try {
                        Thread.currentThread().sleep(1000);
                        System.out.println();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        System.out.println("wait() will release lock");
                        Test.class.wait();
                        System.out.println(Thread.currentThread().getName() + " need hold the lock again, and then to continue...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " will release lock again");
                }
            }
        }, "waitThread");

        Thread notifyThread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " blocked.... for the lock");
                synchronized (Test.class){
                    System.out.println(Thread.currentThread().getName() + " is holding lock...");
                    Test.class.notify();
                    try {
                        Thread.currentThread().sleep(1000);
                        System.out.println();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " will release lock");
                }
            }
        }, "notifyThread");

        waitThread.start();
        Thread.sleep(100);
        notifyThread.start();

    }

}


输出结果:
waitThread is holding lock...
notifyThread blocked.... for the lock

wait() will release lock
notifyThread is holding lock...

notifyThread will release lock
waitThread need hold the lock again, and then to continue...
waitThread will release lock again

Process finished with exit code 0

 

总结:

  1. wait()和notify()方法调用的前提是,二者所在的线程体中(即run()方法体)都需要先通过synchronized获取对象的锁;
  2. 当waitThread线程调用wait()方法后,会释放锁对象线程由RUNNING状态转向WAITING状态,即该线程进入等待队列中;(记住这三点)
  3. wait()方法释放锁对象之前,notifyThread线程会阻塞在synchronzied获取锁对象的位置;而当wait()释放锁后,notifyThread线程会由阻塞状态尝试竞争锁,并拿到锁,开始执行同步块,当执行到notify()方法后,会将waitThread线程从等待队列中移到同步队列中,即notify方法会触发waitThread线程由WAITING非竞争状态转化为BLOCKED状态
  4. 即,notify()方法只是会触发wait()所在的线程由非竞争的等待队列进入锁竞争的同步队列由WAITING状态转向BLOCKED状态;想要执行wait()方法后续代码的前提是waitThread需要先竞争到锁对象,而由于notify()所在的同步块目前正持有锁,所以在notify从方法刚被调用(触发waitThread参与竞争)到所在同步块释放锁(释放waitThread需要的东西)这个过程里,waitThread只能一直阻塞

 

等待通知机制:

  1. 等待线程获取到对象的锁,调用wait()方法,放弃锁,进入等待队列
  2. 通知线程获取到对象的锁,调用对象的notify()方法
  3. 等待线程接受到通知,从等待队列移到同步队列,进入阻塞状态
  4. 通知线程释放锁后,等待线程获取到锁继续执行

从上面叙述可以看出,不管是notifyThread竞争锁,还是notify之后,waitThread需要重新进入同步队列,重新竞争锁,,最后都需要在阻塞状态下竞争同一个锁对象,,因此,等待/通知机制仍依托于同步机制


使用常见细节:

我们做个试验,尝试在notify方法调用后,执行一个while循环,不让其同步块执行完,这样的话,wait()虽然接到了从waiting到blocked的提醒,但是仍然获不到锁,没法继续执行后续代码:

public class Test {

    public static void main(String[] args) throws InterruptedException {

        Thread waitThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Test.class){
                    try {
                        System.out.println(Thread.currentThread().getName() + " hold lock");
                        Test.class.wait();
                        System.out.println(Thread.currentThread().getName() + " hold lock again!!!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "waitThread");

        Thread notifyThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Test.class){
                    System.out.println(Thread.currentThread().getName() + " hold lock");
                    Test.class.notify();
                    while (true);
                }
            }
        }, "notifyThread");

        waitThread.start();
        Thread.sleep(100);
        notifyThread.start();

    }

}


输出结果:
waitThread hold lock
notifyThread hold lock

从输出结果可知,虽然notify()通知了wait()方法,但是由于notify所在同步块存在死循环,也就是一直没法释放wait()需要的锁,所以waitThread线程一直会阻塞下去;


线程状态切换过程

接下来,我们通过getState方法获取线程状态,来更直观的理解wait和notify机制对线程状态改变的过程:

import org.apache.poi.ss.formula.functions.T;

public class Test {

    private static Thread waitThread;

    public static void main(String[] args) throws InterruptedException {

        waitThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Test.class){
                    try {
                        System.out.println(Thread.currentThread().getName() + " hold lock");
                        Test.class.wait();
                        System.out.println(Thread.currentThread().getName() + " hold lock again!!!");
                        for (int i=0; i<5;i++){
                            try {
                                Thread.currentThread().sleep(1000);
                                System.out.println(Thread.currentThread().getName() + "'s state after hold lock again: "
                                        + Thread.currentThread().getState());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "waitThread");

        Thread notifyThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (Test.class){
                    System.out.println(Thread.currentThread().getName() + " hold lock");
                    for (int i=0; i<5;i++){
                        try {
                            Thread.currentThread().sleep(1000);
                            System.out.println(waitThread.getName() + "'s state before notify: " + waitThread.getState());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                    System.out.println("----------------------------------------");
                    Test.class.notify();
                    for (int i=0; i<5;i++){
                        try {
                            Thread.currentThread().sleep(1000);
                            System.out.println(waitThread.getName() + "'s state after notify: " + waitThread.getState());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("----------------------------------------");
                }
            }
        }, "notifyThread");

        waitThread.start();
        Thread.sleep(100);
        notifyThread.start();

    }

}



输出结果:
waitThread hold lock
notifyThread hold lock
waitThread's state before notify: WAITING
waitThread's state before notify: WAITING
waitThread's state before notify: WAITING
waitThread's state before notify: WAITING
waitThread's state before notify: WAITING
----------------------------------------
waitThread's state after notify: BLOCKED
waitThread's state after notify: BLOCKED
waitThread's state after notify: BLOCKED
waitThread's state after notify: BLOCKED
waitThread's state after notify: BLOCKED
----------------------------------------
waitThread hold lock again!!!
waitThread's state after hold lock again: RUNNABLE
waitThread's state after hold lock again: RUNNABLE
waitThread's state after hold lock again: RUNNABLE
waitThread's state after hold lock again: RUNNABLE
waitThread's state after hold lock again: RUNNABLE

Process finished with exit code 0

等待/通知的经典范式:

该范式分为两部分,分别针对等待方(消费者)和通知方(生产者)。

等待方遵循如下原则。

  • 获取对象的锁。
  • 如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
  • 条件满足则执行对应的逻辑。
// 对应的伪代码如下:
synchronized(对象) {

    while(条件不满足) {

        对象.wait();

    }
    
    对应的处理逻辑

}  

理解说明:
while在这里是有意义的,当notify的同步块释锁之后,
wait()竞争得到锁,进入第二轮循环,若此时条件仍不满足,
那么wait()被第二次执行,由于这次执行之前,当前线程仍持有锁,
所以wait有锁可释,不会报错,释完锁之后,当前线程就由RUNNING转向WAITING,
线程进入等待队列,等待下一次notify通知.

通知方遵循如下原则:

  • 获得对象的锁。
  • 改变条件。
  • 通知所有等待在对象上的线程。
// 对应的伪代码如下:
synchronized(对象) {

    // 改变条件得位置不重要 ,只要在同步块执行之前(释锁之前),
    // 因为wait只有在notify释锁后才有机会加锁,进而响应条件的变化
    改变条件

    对象.notifyAll();

}

OpenBullet2 学习研究2-Conditions条件之KeyCheck的使用 上一节我们学习了如何安装Openbullet2以及如何新建一个配置,最后我们再配置里面新建一个Http的请求块,帮助我们发送了第一个请请求。这一节我们来学习check块。当我们发送请求以后,请求返回的内容是否是我们想要的,或者请求发送正确没有,这个我们怎么判断呢?这个时候就要用到check块了。 阅读详情

相关推荐

别再让 AI 瞎写 SAP 代码了!这套 Claude Code Skill 的验证机制才是关键

本文深入解析了专为SAP CAP开发设计的AI辅助工具sap-cap-capire的技术架构。该工具采用四层设计:协议层集成MCPLSP实现实时模型访问与语法检查;智能层通过4个专业化Agent(数据建模、服务开发等)分工协作;验证层确保代码质量;知识层存储文档模板。这种工程化设计解决了通用AI在CAP开发中面临的上下文不足、专业性缺失代码质量保证等核心问题,通过本地化服务实时反馈机制显著提升了开发效率。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 834

waitnotify的使用

waitnotify的使用

qq_62949535的博客 8282

Python + 基于爬虫技术的 Lofter 内容批量爬取与分类保存!.zip

Python + 基于爬虫技术的 Lofter 内容批量爬取与分类保存!.zip

Java线程基础(13):wait()notify()

简介 本文讲解Java中wait()notify(),通过一个标准的使用实例,来讨论下这两个方法的作用使用时注意点,这两个方法被提取到顶级父类Object对象中,地位等同于toString()方法。 一、wait()notify()含义 wait()方法是让当前线程等待的,即让线程释放了对共享对象的锁,不再继续向下执行。 wait(long timeout)方法可以指定一个超时时间,过了这个时间如果没有被notify()唤醒,则函数还是会返回。如果传递一个负数timeout会抛出I...

mingyuli的博客 1万+

wait方法 与 notify方法

1. 线程状态图 这是线程的7状态模型图,常见的7大状态之间的转换关系也在上面。多线程之间的通信主要用到4个方法,wait()、wait(long time)、notify()、notifyAll(),其他方法在多线程基础中都有介绍。 wait():作用是使当前线程从调用处中断并且释放锁转入等待队列,直到收到notify或者notifyAll的通知才能从等待队列转入锁池队列,没有收到停止会一直死等。 wait(long time):相比wait多了一个等待的时间time,如果经过time(毫秒)时

weixin_43808717的博客 1万+

多线程初阶(六):wait & notify

多线程 --- wait & notify

2401_83595513的博客 2296

Java多线程wait()notify()方法图解

多线程场景下 wait notify 方法详解,注意事项,内部阻塞队列等待队列的过程,waitsleep方法的区别

VIBE的博客 4233

【JavaEE初阶 — 多线程】wait() & notify()

wait() & notify()

OuO-1 的博客 1798

JAVA-wait()notify()

大家应该都知道,线程之间是抢占式随机执行的,但是我们并不希望这样。因为这样非常混乱,并不好去预估程序的执行结果。我们甚至希望,线程之间能够配合执行,那么我们就可以使用wait()notify()来做到。

Lizhihao_的博客 1535

【多线程】wait()notify()

本期内容主要讲解如何协调多个线程之间的执行顺序,使用wait()方法notify()方法解决,详细介绍这两个方法,并同时介绍常见面试题,wait()与join()、sleep()方法之间的区别。

爱编程爱运动的博客 5121

wait() 一定需要notify()唤醒吗?

wait() 一定需要notify()唤醒吗?20120810       写这篇文章是源于论坛里的一个帖子,   "线程同步问题,分析下程序运行结果"  其地址为:      http://topic.csdn.net/u/20120808/17/f1742060-7501-430b-b509-a492eef535f5.html.       当时按照一般的wait(),notify()思想做了

nmyangym的专栏 6866

【多线程初阶】wait() & notify()

wait()与sleepjoin的区别 & notify() & notifyAll() & 协调多个线程之间的执行顺序

2503_90322569的博客 924

一个理解wait()notify()的例子

下面是我原来在CSDN论坛上看到的一个贴子,涉及到同步,wait(),notify()等概念的理解,我试着根据原来的一些回复Think in Java上的相关概念将wait()notify()这两个方法剖析了一下,欢迎指教.问题如下:file://分析这段程序,并解释一下,着重讲讲synchronized、wait(),notify 谢谢!class ThreadA {  public

xm4014的专栏 1万+

8.多线程(5) --- waitnotify的使用

上一个博客中我们学习volatile关键字,这个博客中我们学习waitnotifywait 是 等待,notify是通知。使用这两个方法,可以让后执行的逻辑,等待先执行的逻辑先执行,虽然无法直接干预调度器的调度顺序,但是可以让后执行的逻辑(线程)等待,等待到先执行的逻辑跑完,通知一下当前的线程,让他继续执行。

xxhh156的博客 2031

java——waitnotify的基本用法

wait的用法以及它的3种结束条件:1.notify2.interrupted3.时间超时

xhhhx_的博客 1万+

[Java 多线程技术](七)使用wait/notify实现线程间通信

线程是操作系统中独立的个体,但这些个体如果不经过特殊处理就不能成为一个整体。线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更加强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控监督。 1. 等待通知机制 1.1 不使用等待/通知机制实现线程间通信   创建新项目,在实验中使用sleep()结合while(true)死循环法来实现多个线程间通信。代码如下: public class MyList { priva.

YHJ 2396

线程间的通信---wait()notify()

wait() 作用:让当前线程进入等待状态(使线程停止运行),同时,wait()也会让当前线程释放它所持有的锁,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,当前线程被唤醒(进入“就绪态”) 注意: 1.方法wait()的作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法是用来将当前线程置入“预执行队列”中,并且在wait()所在的代码处停止执行,直到接到通知或被中断为止。 2. wait()方法只能在同步方法中或同步块中调用。如果..

m0_46657493的博客 1272

看完立刻搞懂--waitnotify

还不理解多线程中waitnotify是如何配合工作的吗?线程的生命周期是什么?小玉手把手教你........

m0_73609313的博客 1655

【Java多线程编程】waitnotify方法详解

本期讲解:Java 多线程中的 wait方法、notify方法、notifyAll方法,wait方法与sleep方法之间的区别。

我的主页 4473

waitnotify的用法

432

gulanga5的博客 1370
上一篇: Java synchronized阻塞的同步队列现象分析
下一篇: CAS自旋volatile变量
Ethan Zeng
博客等级 码龄9年 9粉丝 40原创
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值