java多线程学习4:wait、notify、notifyall。生产者消费者实例

多线程中wait()、sleep()、notify()和notifyAll()方法异同点【面试】 现在面试基本上都会被问及到多线程,就有很高概率问到wait() 和 sleep() 这两者的区别 1、wait()、sleep() 方法相同点 (1)都是对线程的操作; (2)都需要抛异常; (这一点我遇到很多人答错,记住这两者都会抛异常) (3)都会让当前运行线程进入阻塞状态。 2、wait()、sleep() 方法不同点 (1)使用位置不同: wait() 方法必须在同步代码中,sleep() 则不需要; (2)申明位置不同: wait() 方法是 Object类 中的方法,sleep() 方法是 T. 阅读详情
大纲:
1、wait
2、notify
3、notifyall
4、wait和sleep的区别
5、单一生产者消费者代码
6、多生产者消费者代码

wait
官方文档太多。总结为下面几点
1、调用wait方法必须要有monitor。这个monitor就是synchorized中的那个。
2、调用wait后,当前线程会进去wait set(线程休息室)并释放当前锁占用。直到thismonitor的notify、notifyall、或者wait超时才能唤醒。
3、当发生当前上述情况后,线程会从线程wait set中出来,并重新变为可调度(runnable),通常会争抢这个锁。当它获取到执行权时,就会恢复到之前的执行状态。

notify
还是总结一下官方文档说的
1、这个方法用来唤醒是用同一mointor的wait中的线程。
2、当前线程调用monitor的notify后,线程并不会马上释放锁。需要当前线程放弃锁占用。
3、调用Notify需要首先获取锁占用
4、当wait的线程有多个时,notify的唤醒时随机的(可能根据不同jvm有不同的策略)。

notifyall
这个就真的没什么好说的了。唤醒所有wait住的线程(同1monitor)

wait和sleep的区别
1、wait是object的实例方法,sleep是thread的静态方法。
2、wait和sleep都会block住当前线程。但wait会释放锁占用而sleep不会释放锁,只是然出cpu的执行权。
3、wait的使用必须要在同步代码块中,同时必须时当前monitor调用。sleep没有这个限制

单生产者消费者实例

package com.puqiuyu.thread.blog;

public class Window {
    private int ticket;

    private final Object MONITOR;

    private boolean isProduced;

    public Window() {
        this.MONITOR = new Object();
        this.isProduced = false;
    }

    public void produce() {
        synchronized (MONITOR) {
            while (isProduced) {
                try {
                    MONITOR.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            ticket++;
            System.out.println("produce ticket : " + ticket);
            isProduced = true;
            MONITOR.notify();
        }
    }
    public void consume() {
        synchronized (MONITOR) {
            while(!isProduced) {
                try {
                    MONITOR.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("consume ticket : " + ticket);
            isProduced =false;
            MONITOR.notify();
        }
    }

}
package com.puqiuyu.thread.blog;

public class ProducerAndConusmerDemo {
    public static void main(String[] args) {

        final int count = 1000;
        final Window window = new Window();
        Thread producer = new Thread(()->{
            for (int i = 0; i < count; i++) {
                window.produce();
            }
        });
        Thread consume = new Thread(()->{
            for (int i = 0; i < count; i++) {
                window.consume();
            }
        });
        producer.start();
        consume.start();
    }
}

上面这段程序,执行不会存在问题。但如果改成多生产者消费者就会出现问题。

现在起了2个生产者、两个消费者。结果线程假死
通过jstack来分析一下

"consumer_1" #12 prio=5 os_prio=31 tid=0x00007fd23c016000 nid=0x5303 in Object.wait() [0x000070000fad5000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000007955f57b8> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:502)
    at com.puqiuyu.thread.blog.Window.consume(Window.java:34)
    - locked <0x00000007955f57b8> (a java.lang.Object)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo.lambda$3(ProducerAndConusmerDemo.java:25)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo$$Lambda$4/142257191.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

"consumer_0" #11 prio=5 os_prio=31 tid=0x00007fd23c015000 nid=0x5103 in Object.wait() [0x000070000f9d2000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000007955f57b8> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:502)
    at com.puqiuyu.thread.blog.Window.consume(Window.java:34)
    - locked <0x00000007955f57b8> (a java.lang.Object)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo.lambda$2(ProducerAndConusmerDemo.java:20)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo$$Lambda$3/135721597.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

"producer_1" #10 prio=5 os_prio=31 tid=0x00007fd23b034000 nid=0x4f03 in Object.wait() [0x000070000f8cf000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000007955f57b8> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:502)
    at com.puqiuyu.thread.blog.Window.produce(Window.java:19)
    - locked <0x00000007955f57b8> (a java.lang.Object)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo.lambda$1(ProducerAndConusmerDemo.java:15)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo$$Lambda$2/303563356.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

"producer_0" #9 prio=5 os_prio=31 tid=0x00007fd23a8bf800 nid=0x4d03 in Object.wait() [0x000070000f7cc000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000007955f57b8> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:502)
    at com.puqiuyu.thread.blog.Window.produce(Window.java:19)
    - locked <0x00000007955f57b8> (a java.lang.Object)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo.lambda$0(ProducerAndConusmerDemo.java:10)
    at com.puqiuyu.thread.blog.ProducerAndConusmerDemo$$Lambda$1/531885035.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
可以看到 p0\p1\c0\c1都在wait这个<0x00000007955f57b8>monitor。
什么情况导致呢,因为notify只唤醒一个,且有随机性。那么当一个producer wait之后刚好唤醒了另一个producer。而此时已经生产了1个。rpdoucer有wait了。那么就会出现这种问题。
所以我们将notify改为notifyall解决这个问题。
Java 多线程学习笔记 线程通讯 wait notify notifyAll的理解 Java 多线程学习笔记 线程通讯 wait notify notifyAll的理解 wait()、 notify()、 notifyAll()是Object类的实例方法,是多线程之间通信的手段 2. wait():当某个条件无法满足,当前线程又没有能力解决时,等待直到条件满足 3. notify():当前线程认为其它线程所等待的条件已经满足时,通知某个正在等待 的线程 4. notify... 阅读详情

相关推荐

手把手教你用DCA1000EVM解析IWR6843毫米波雷达数据(附MATLAB代码)

本文提供了一份详尽的实战指南,手把手教你使用DCA1000EVM采集并解析TI毫米波雷达IWR6843的原始数据。内容涵盖硬件连接配置、mmWave Studio参数设置、LVDS数据流结构解析,并附有核心MATLAB代码,详细演示了从原始二进制文件到距离-速度谱的信号处理全链路,帮助开发者快速掌握数据解析与处理的关键步骤。

terraform7cloud的博客 228

Java-线程的运行状态

参考: 学习java线程状态和看懂thread dump文件中的线程信息 Java线程中wait状态和block状态的区别? 1,线程状态为“waiting for monitor entry”: 意味着它 在等待进入一个临界区 ,所以它在”Entry Set“队列中等待。 此时线程状态一般都是 Blocked: java.lang.Thread.State: BLOCKED (o

火星男孩的分享空间 2646

基于大模型的自动驾驶智能体:Agent-Driver架构、训练与实战指南

自动驾驶系统正从传统的模块化流水线向以智能体为核心的新范式演进。其核心原理在于将车辆视为一个能够与环境持续交互的自主决策智能体,通过多模态感知、记忆管理和基于大模型的推理能力,实现对复杂交通场景的理解与应对。这一技术价值在于利用大模型的常识推理和泛化能力,有望解决传统方法在长尾场景下面临的挑战。在应用场景上,智能体驱动架构特别适合处理动态交互密集、需高层语义理解的城区驾驶、无保护转弯及突发状况应对。本文聚焦的Agent-Driver项目,正是这一方向的典型实践,它通过融合视觉、语言大模型与强化学习,构建了一

weixin_28729843的博客 529

【20220608作业①】线程的BLOCKED状态和WAITING状态的区别

BLOCKED与WAITING

今天复习了吗? 2405

鸿蒙OpenHarmony南向开发 轻量系统芯片移植指南(一)

OpenHarmony系统采用"系统>子系统>部件"层级架构,支持功能模块化裁剪。本文介绍了关键子系统及移植方法:1)启动恢复子系统负责内核到应用间的进程初始化,需配置启动入口标识及链接脚本;2)文件子系统提供基础文件操作接口,需适配HAL层文件读写功能,可通过Flash模拟、轻量文件系统或厂商自有方案实现。移植过程需修改config.json配置,添加对应组件定义及功能实现。系统采用模块化设计,开发者可根据实际需求灵活配置所需子系统功能。

yx525623的博客 1134

高能物理相关软件

国内高能物理实验背景     研究物质最深层次结构及相互作用的前沿基础科学。 现代高能物理实验的要素    实例源 、 探测器、   电子学、  触发 DAQ、  原始数据、 刻度、重建 、物理分析、  成果  。 离线软件的地位和作用。    是硬件设备和物理学家的桥梁,是从数据到物理成果转化中的关键和重要的环节。 高能物理实验及其特点 独一无二性,实验规模越来越大,努力省钱(使用

Alan Zhuang的博客 3301

Java线程的6种状态及切换(透彻讲解)

Java中线程的状态分为6种。 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。 2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状...

潘建南的博客 27万+

用Origin快速拟合荧光寿命、PL Decay (TRPL)数据分析处理

用Origin快速拟合荧光寿命、PL Decay (TRPL)数据分析处理

A20802013的博客 2万+

Java线程中的sleep、wait和block:区别与联系详解

Java多线程中sleep()、wait()和阻塞的区别:1) sleep()是Thread类方法,不释放锁,线程进入TIMED_WAITING状态;2) wait()是Object方法,必须在同步块调用,会释放锁,线程进入WAITING/TIMED_WAITING状态;3) 阻塞(BLOCKED)是被动状态,发生在竞争同步锁失败时。关键区别在于锁的行为和线程状态变化,sleep()持锁休眠,wait()放锁等待,阻塞是抢锁失败。正确使用三者能有效实现线程协作,避免死锁问题。

ze15829163918的博客 665

【超分辨率(Super-Resolution)】关于【超分辨率重建】专栏的相关说明,包含专栏简介、专栏亮点、适配人群、相关说明、阅读顺序、超分理解、实现流程、研究方向、论文代码数据集汇总等

本专栏研究领域为【超分辨率重建】,涵盖图像超分、视频超分,实时超分,4K修复等方面。主要内容包括主流算法模型的论文精读、论文复现、毕业设计、涨点手段、调参技巧、论文写作、应用落地等方面。算法模型从SRCNN开始更新至今,一般是一篇论文精读对应一篇论文复现。论文精读详解理论,归化繁为简,归纳核心,积累词句,培养阅读论文和论文写作能力。论文复现依托Pytorch代码,实现完整的模型训练流程,总结调参方法,记录碰到的bug,论文插图可视化,培养读写代码能力、做实验的能力、以及应用落地能力。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 3万+

C#上位机实战:PLC与检测设备无缝对接,构建产品质量实时判定系统

本文分享了基于C#开发的汽车零部件质量检测系统实现经验。系统采用三层架构:设备层(PLC/视觉相机/三坐标)、通信层(OPC UA/SDK/串口)和应用层(数据采集/判定/存储)。重点解决了三大技术难点:1)通过OPC UA订阅模式将PLC通信延迟从500ms降至50ms;2)反编译厂商Demo破解视觉SDK对接难题;3)采用时间戳+产品ID实现多设备数据同步。系统上线后质检人员减少67%,误判率降至0.5%,数据追溯效率显著提升。文章强调工业场景下稳定性优先于技术复杂度,实用经验值得借鉴。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 802

java线程wait_Java线程中wait状态和block状态的区别?

Thread is in the Blocked state while waiting for the monitor lock to enter a synchronized block or method or to reenter a synchronized block or method after calling Object.wait().这个地方是说synchronized会导致...

weixin_39521835的博客 1411

多思计组实验实验六 微程序控制器实验

实验六 微程序控制器实验

qq_53089329的博客 3789

Java多线程学习之wait、notify/notifyAll 详解

点击“终码一生”,关注,置顶公众号 每日技术干货,第一时间送达! 1、wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。 2、wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。 3、 由于 wait()、notify/notifyAll() 在synchronized 代码块执行,说

终码一生 1870

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Java线程协作:深入理解wait、notify与notifyAll

在多线程编程中,线程调度的不确定性常常让开发者头疼。如何让多个线程按照既定顺序执行?如何实现线程间的协作?Java提供了wait()、notify()和notifyAll()这套经典线程通信机制。本文将深入解析这三个核心方法的使用技巧,助你掌握线程协作的精髓。

weixin_69555518的博客 1035

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

多线程学习篇五:wait / notify / notifyAll

wait():让进入 object 监视器的线程到 waitSet 等待notify():在 object 上正在 waitSet 等待的线程中挑一个唤醒notifyAll():让 object 上正在 waitSet 等待的线程全部唤醒它们都是线程之间进行协作的手段,都属于 Object 对象的方法。必须获得此对象的锁,才能调用这几个方法即 Guarded Suspension,用在一个线程等待另一个线程的执行结果。

好记性不如烂笔头 1065

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

wait,notify,notifyAll从使用到原理图详解(含高频面试题和使用wait_notify实现生产者消费者问题)

wait,notify,notifyAll从使用到原理图详解(含高频面试题和使用wait_notify实现生产者消费者问题)

2301_77615930的博客 1083

【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非常重要的,本博客主要讲解多个线程之间使用wait()/notify()/notifyAll()来进行交互的场景。 一wait()/notify()/notifyAll(): 首先我们来看一下它们的

(* ̄︶ ̄) 2366

Java线程的状态及wait、notify/notifyAll 详解

Java中线程的状态分为以下6种: 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。 2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪...

android开发笔记 1234

Java使用wait()、notify()、notifyAll()实现生产者消费者模式

前言: 1. wait()、notify()、notifyAll()三个方法不是随随便便就能用的,这三个方法一定要在同步代码块中调用的。 2. 同步代码块中的锁最好是使用临界资源,也最好使用临界资源对象的 wait()、notify()、notifyAll()。 3. 如果有多个生产者和多个消费者,那么尽量不要调用notify()、而要用notifyAll()。因为如果某一生产者使用noti...

a907691592的博客 655

java多线程的wait(), notify(), notifyAll()的用法

参考博客: java wait()方法用法详解:https://www.jianshu.com/p/def7f016dd5e 你真的懂wait、notify和notifyAll吗:https://www.jianshu.com/p/25e243850bd2?appinstall=0 诡异的java.lang.IllegalMonitorStateException:https://blog.cs...

menghuanzhiming的博客 1668

用wait和notify/notifyAll实现生产者消费者模式

生产者消费者模式的实现方式有很多种,比如采用Condition条件变量或者利用阻塞队列来进行实现。本文将采用Object中自带的wait和notify/notifyAll方法来实现这个模式。实现代码如下: import java.util.LinkedList; public class ProducerConsumerPattern{ public static final int MA

Just Do IT 1793

java中notify() 和 notifyAll()

notify()和都是用于唤醒等待线程的方法,但它们的适用场景有所不同。notify()用于唤醒一个等待线程,适用于单线程唤醒的简单场景,而则用于唤醒所有等待线程,适用于复杂场景以避免信号丢失和死锁问题。在多线程编程中,选择使用notify()还是需要根据具体的应用场景和需求来决定。

Flying_Fish_roe的博客 671

Java-Notify、NotifyAll、Wait使用

上篇文章中学到了Synchronized的使用,这篇文章就介绍一下Notify、NotifyAll、Wait。 1.Notify、NotifyAll、Wait 这三个方法均属于Object类,但是它们多用在多线程中。 三者的区别以及各自的含义(使用的注意事项): notify: 唤醒一个正在wait当前对象锁的线程,并继续执行 notifyAll:唤醒全部在wait当前对象锁的线程,所有线程...

qq_34341338的博客 427
上一篇: java多线程学习3:如何结束一个线程
下一篇: JAVA多线程学习5:自己实现一个boolean锁
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值