JAVA多线程基础篇 7、线程协作 wait()和notify()

4090显卡实测:PointPillars在KITTI数据集上的3D目标检测复现全流程(附避坑指南) 本文详细记录了在NVIDIA RTX 4090显卡上,从环境搭建、数据处理到模型训练与评估,完整复现PointPillars算法在KITTI数据集上进行3D目标检测的全流程。重点分享了版本配置、数据预处理、性能调优及常见问题的避坑指南,帮助开发者高效利用硬件资源,成功跑通并理解这一经典3D检测项目。 阅读详情

wait()和notify()都是定义在Object类中,那为什么如此设计呢?。因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调用wait()和notify(),并且只有同一把锁才能对线程进行操作,不同锁之间是不可以相互操作的。

  • wait

wait()提供三种构造方法,wait()是让线程一直处于等待状态,直到手动唤醒;而wait(long timeout)可以指定等待时间,之后会自动唤醒。

  • notify

notify()唤醒等待的线程,如果监视器种只有一个等待线程,使用notify()可以唤醒。但是如果有多条线程notify()是随机唤醒其中一条线程,与之对应的就是notifyAll()就是唤醒所有等待的线程。

1 用wait和notify实现线程同步

这是leetcode的1115题。

class FooBar {
  public void foo() {
    for (int i = 0; i < n; i++) {
      print("foo");
    }
  }

  public void bar() {
    for (int i = 0; i < n; i++) {
      print("bar");
    }
  }
}

两个不同的线程将会共用一个 FooBar 实例:

线程 A 将会调用 foo() 方法,而
线程 B 将会调用 bar() 方法
请设计修改程序,以确保 “foobar” 被输出 n 次。

示例 1:

输入:n = 1
输出:“foobar”
解释:这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,“foobar” 将被输出一次。
示例 2:

输入:n = 2
输出:“foobarfoobar”
解释:“foobar” 将被输出两次。

提示:

1 <= n <= 1000

1.1 实现方法

增加flag状态。在synchronized的时候,foo方法和bar方法监控flag的状态。

  • Foo:
    • 如果flag是Flase,则会wait。
    • 如果自己被唤醒,则表示,Bar完成了其任务,该Foo继续完成任务。
    • 于是Foo打印
    • 打印完成了后将标志flag重置为相反。
  • Bar:
    • 如果flag是true,则会wait。
    • 如果自己被唤醒,则表示,Bar完成了其任务,该Foo继续完成任务。
    • 于是Foo打印
    • 打印完成了后将标志flag重置为相反。
class FooBar {

        private int n;

        private volatile boolean flag = true;

        public FooBar(int n) {
            this.n = n;
          }

        public void foo(Runnable printFoo) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                // printFoo.run() outputs "foo". Do not change or remove this line.
                synchronized (this){
                    while (!flag){
                        wait();
                    }
                    printFoo.run();
                    flag=!flag;
                    notify();
                }
            }
        }

        public void bar(Runnable printBar) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                synchronized (this) {
                    while (flag) {
                        wait();
                    }
                    // printBar.run() outputs "bar". Do not change or remove this line.
                    printBar.run();
                    flag=!flag;
                    notify();
                }
            }
        }
    }
  • wait和while
    • 在这个程序当中wait和while是配对使用的。因为如果线程wait后,醒来第一件事就是执行wait之后的代码。
    • 如果是if 则不会进行再次判断。
    • 如果是while,则会再次判断flag标志,如果当前flag标志不相符,自己还会再次wait。

2 也可以使用ReentrantLock和condition实现

condition的signal、signalAll和await方法,可以替代notify、notifyAll、wait方法。

一个lock可以设定多个condition。每个condition后可以跟随多个等待队列。

class FooBar {

        private int n;

        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        private boolean flag = true;

        public FooBar(int n) {
            this.n = n;
          }

        public void foo(Runnable printFoo) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                lock.lock();
                while (!flag){
                    condition.await();
                }
                // printFoo.run() outputs "foo". Do not change or remove this line.
                printFoo.run();
                flag=!flag;
                condition.signalAll();
                lock.unlock();
            }
        }

        public void bar(Runnable printBar) throws InterruptedException {

            for (int i = 0; i < n; i++) {
                lock.lock();
                while (flag){
                    condition.await();
                }
                // printBar.run() outputs "bar". Do not change or remove this line.
                printBar.run();
                flag=!flag;
                condition.signalAll();
                lock.unlock();
            }
        }
    }

总结

wait和nofity是成对使用的,最好使用notifyAll(),这样可以唤起这条队列里所有的线程。

同时还需要注意的是,wait和while需要配对使用。

多线程系列在github上有一个开源项目,主要是本系列博客的实验代码。

https://github.com/forestnlp/concurrentlab

如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。

您的支持是对我最大的鼓励。

[特殊字符] PetaLinux Qt 程序(WindRadar)无法自动启动问题解决文档 摘要:本文档解决了PetaLinux 2020.1系统中Qt程序(WindRadar)无法开机自动显示界面的问题。通过分析发现,自动启动时缺少DISPLAY=:0.0环境变量导致Qt找不到显示设备。最终在autostart.sh脚本中添加该变量,并完善了字体加载、驱动加载、显示设备检测等流程,确保程序正常自启显示界面。完整脚本包含路径检测、环境配置和错误处理,经验证各项功能均正常运行。 阅读详情

相关推荐

ROS教程(四):RVIZ使用教程(详细图文)

前言 根据前面的教程已经学会了创建功能包,那么本篇文章主要内容则是通过节点来发布数据至RVIZ

Leslie的博客 17万+

Java多线程中的 wait() 和 notify() 方法

多线程并发的场景下,有时需要某些线程先执行,这些线程执行结束后其他线程再继续执行, wait()和notify()是Object类的方法,用于线程的等待与唤醒,必须搭配synchronized 锁来使用。

sinat_31583645的博客 4351

从零上手SKILL脚本:在Virtuoso中实现版图绘制自动化

本文详细介绍了如何使用SKILL脚本在Virtuoso中实现版图绘制自动化,从基础操作到高级技巧全面覆盖。通过抓取操作日志、转换交互式函数为程序式函数,以及核心函数深度解析,帮助读者快速掌握SKILL脚本编程,大幅提升版图设计效率。文章还提供了实际工程应用案例和调试优化技巧,适合从零开始的初学者。

weixin_28742653的博客 764

java并发编程之wait&notify VS lock&condition

jdk5之前线程同步可以用synchronized/wait/notify来进行控制,jdk5以后新添加了lock/condition。他们之间有什么联系与区别的?本文就用一个例子循序渐进的给大家展示一下:首先来看一个有界缓存的例子:abstract class BaseBoundedBuffer&lt;V&gt; { private final V[] buff; private...

若鱼的专栏 713

Python气象雷达数据处理实战:用PyCINRAD从基数据到PPI图的完整流程

本文详细介绍了使用PyCINRAD库处理气象雷达基数据并生成PPI图的完整流程,涵盖环境配置、数据读取、反射率与速度数据提取、可视化优化等关键步骤。通过实战案例演示如何从原始雷达数据到专业级PPI图像生成,为气象研究和业务应用提供高效解决方案。

yog99的博客 758

YOLOv8改进——引入可变形卷积DCNv3

本文只讲解在YOLOv8的代码中添加DCNv3的操作流程, 具体的原理参见上述的链接~是pytorch实现的版本,只要基础的pytorch环境安装正确就不会出错。是C++实现版本,必须先在上一步编译成功,或者安装好了轮子,否则会报错。但是在实际的训练过程中,C++版本的运行速度更快,推荐使用C++版本。(具体怎么修改,都可以自己决定,然后通过实验看看效果如何)文件夹,该文件夹下的内容就是实现DCNv3算子的核心代码。中,下图中的列表里添加。

zyw2002的博客 3万+

Java多线程的wait()和notify()例子 转载

示例代码1:   package com.pinfo.test;   public class ThreadTest {   /**   * @param args   */   public static void main(String[] args) {   String lock = "lock";   MyThread myThread = new MyThre...

205

RTCA DO-160G标准详解:航空电子设备的全面环境适应性测试指南

第二章的主要目的是提供标准中使用的术语和定义。了解这些术语对于准确理解标准的要求至关重要,特别是在技术实施过程中。RTCA DO-160G 涉及多个学科的知识,包括航空、电子、电磁学和机械工程,因此需要确保使用的术语在所有学科中具有一致的定义。为了确保测试人员和工程师在执行测试时对所有条件和要求的理解一致,RTCA DO-160G 标准中定义了大量术语。环境应力:指的是设备在操作过程中可能遇到的外部物理或化学条件,包括温度、湿度、振动等。电磁干扰(EMI)

qq_41854911的博客 5276

Java之wait()和notify()实例讲解

Object对象的wait()和notify(): wait:导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法,该方法是会释放锁的。 notify:唤醒正在等待对象监视器的单个线程。 如果任何线程正在等待这个对象,其中一个被选择被唤醒。 选择是任意的,并且由实施的判断发生。 线程通过调用wait方法之一等待对象的监视器。 该方法不释放锁的。 wait和n...

玻璃汽水的博客 1804

RT-DERT安卓部署教程

这个文档中的代码案例,实现了拍照和选图识别,两个功能,可以看效果图。UI做了美化:显示类别机和数量。代码下载地址:通过网盘分享的文件:android_rtdert.zip链接: https://pan.baidu.com/s/1k6e-d_lov1OPgUmit5i_cA?pwd=hpfi 提取码: hpfi–来自百度网盘超级会员v8的分享。

AIOT魔法师 196

RT-DETR改进策略【卷积层】| CVPR2025 GBConv轻量门控瓶颈卷积 低秩瓶颈降参 + 门控聚焦形态,强效捕捉纤细目标

裂缝形态不规则、纹理纤细,传统卷积参数大、计算冗余,且无法动态聚焦裂缝形态;背景噪声强易干扰特征提取,需要轻量且能自适应聚焦裂缝形态的卷积单元,因此提出轻量门控瓶颈卷积 GBC。

Limiiiing的博客 140

java 线程安全问题,解决线程安全问题——同步代码块,同步方法,Lock锁,Object类中wait方法,notify方法。等待唤醒案例。

1、线程安全问题 线程出现安全问题的代码: /* 实现卖票案例 */ public class RunnableImpl implements Runnable{ //定义一个多个线程共享的票源 private int ticket = 100; //设置线程任务:卖票 @Override public void run() { //使用死循环,让买票操作重复执行 while (true) { //先

Gaoju12138的博客 939

第8讲:基于CST PCB Studio的电源完整性仿真(IR Drop + PDN)

本文系统介绍了电源完整性(PI)仿真的两大核心模块:直流IRDrop仿真与交流PDN阻抗仿真。文章详细阐述了两种仿真的原理、算法(PEEC和3DFE-FD)及完整操作流程,包括参数配置、软件实操步骤和常见问题解决方案。IRDrop仿真用于分析直流供电压降问题,PDN仿真则针对高频电源噪声和谐振问题。文中还提供了优化建议和故障排查方法,如调整铜箔厚度、优化电容布局等,为高速数字系统的电源完整性设计提供了全面的技术指导。(149字)

一只豌豆象的博客 239

Java多线程基础-7:wait() 和 notify() 用法解析

详解Java多线程编程中,wait()和notify()方法的使用方式和注意事项,配合代码案例~

wyd_333的博客 8414

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

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

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

VIBE的博客 4249

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

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

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

mingyuli的博客 1万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

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

wait() & notify()

OuO-1 的博客 1813

Java多线程wait()和notify()系列方法使用教程(内涵故事)

本文讲解Java中`wait()`、`notify()`,通过一个标准的使用实例,来讨论下这两个方法的作用和使用时注意点,这两个方法被提取到顶级父类`Object`对象中,地位等同于`toString()`方法,所以本文带你从零开始搞懂它们的用法,在文章最后,准备了一个《捡肥皂》的故事,就算你没写过代码,读了此故事也能明白`wait()`、`notify()`系列方法在程序中的作用了,也算是在1024程序员节送给大家的彩蛋了。

五道口 9735

Java wait() notify()方法使用实例讲解

1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。   2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁,或者叫管程)   3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;

Java 之 道 4万+

【多线程】wait()和notify()

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

爱编程爱运动的博客 5129

【多线程基础】 wait和notify

​线程等待wait()和通知notify(),主要用于多线程之间的通信协作,而且这两个方法都是属于Object类,说明任何对象都可以调用这两个方法。 当在一个实例对象上调用了wait()方法之后,当前线程就会在这个对象上等待。直到另外的线程调用了该对象的notify()方法,处于等待状态的线程才得以继续进行。 这样,多线程之间就可以用这两个方法进行通信协作了。

书生-w的博客 2万+

Java多线程——线程间的通信,wait() 与 notify()

1、概述 针对同一个资源的操作有不同的线程 2、例如: 通过设置线程和获取线程,针对同一个对象进行操作 3、线程的状态转换

Lemon 4449

深入理解Java多线程中的wait(),notify()和sleep()

大家在学习Java的过程中,势必要进行多线程的系统学习,这部分内容知识对于你在工作中的影响是极大的,并且在面试的过程中,这部分知识也是必然会被问到的。既然多线程的知识如此重要,那么我们就不能浅尝辄止。在这篇文章中,我想通过阅读源码的方式给大家分享一下我自己对于Java中wait(),notify()和sleep()的理解,并且在后面我也做一些内容上的扩展,与大家共同思考。如果在文章中有描述不妥或者

小游的博客 2万+

多线程中wait()与notify()和sleep()的区别

今天又来讲讲我们之前只讲了一点的Javaee基础知识,今天要理解的是wait与notify,关于多线程这两个方法我们也是要理解的,那么我们今天就开始来深入理解一下。

2302_81249757的博客 870

多线程编程-wait()与notify()

由于线程之间是抢占式执行的,因此线程之间的执行先后顺序总是难以预知的。但是实际开发中我们总是希望能够合理的协调多个线程之间的执行先后顺序。wait()/wait(long timeout):让当前的线程进入等待状态;notify()/notifyAll():唤醒当前的对象上等待的那个线程;wait()、wait(long timeout)、notify()、notifyAll()都是Object类的方法。

zcx777123的博客 1193

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

在Java多线程环境中,线程之间是抢占式执行的,线程的调度是随机的.这就很难受了. 在很多情况下我们希望线程以我们想要的顺序来执行. 这就需要wait和notify这两个方法wait和notify方法用于实现线程间的协作和通信.wait方法使线程进入等待状态,notify方法唤醒一个等待线程,notifyAll方法唤醒所有等待线程。通过上述三个方法,可以使线程按照特定的顺序执行或者等待某个条件满足后再执行。希望这篇文章能帮到你!专栏:《从零开始的Java学习之旅》在不断更新中,欢迎订阅!

云泽野の编程日记 1777
上一篇: 编程学习的心理建设
下一篇: 一遍就能懂的UML
悟空学编程
博客等级 码龄12年 32粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值