java并发 wait,notify,notifyAll,synchronized(一)

       首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

  java.lang.IllegalMonitorStateException:current thread not owner

 

方法的详细解释:

  wait():

  等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。

调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

  notify():

  唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

  notifyAll():

  唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

 

    可以认为,每个对象实例都有一个wait set线程的休息室,当在该实例调用wait()方法的时候,就将当前线程放入该对象实例的wait set,并释放该对象上的锁。当在改对象上调用notify,或者notifyAll的时候,就是释放该对象wait set休息室里面的线程。

    由此,可以构建一系列的线程安全工具类

 

代码实例:

 

/**
 * 
 */
package com.mutex;

/**
 * 用wait(),notify()实现线程的互斥
 * 
 * 当MainTask运行10次以后,SubTask运行5次,如此依次循环交替执行
 * 
 */
public class MainClient {
	
	//决定线程是否运行
	public static volatile boolean notifyRun=true;
	
	//对象锁
	public static final Object Lock=new Object();
	

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
	
		//主任务运行
		new Thread(new MainTask()).start();
		
		Thread.sleep(1000);
		
		//子任务运行
		new Thread(new SubTask()).start();
		

	}

}

 

 

     

package com.mutex;

public class MainTask implements Runnable {

	private int n = 10;


	@Override
	public void run() {

		while (true) {
			
			System.out.println(" -------- MainTask -----------");
			
			//获取对象MainClient.Lock上的锁
			synchronized (MainClient.Lock) {
				
				if(!MainClient.notifyRun){
					//唤醒MainClient.Lock wait set中的所有线程
					MainClient.Lock.notifyAll();
					MainClient.notifyRun=true;
				}
				
				if(MainClient.notifyRun){
					
					for (int i = 1; i <= n; i++) {
						System.out.println("MainTask run." + i);
					}
					
					try {
						//本线程放入wait set,释放对象MainClient.Lock上的锁
						MainClient.Lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}

		}

	}
}

 

 

 

    

package com.mutex;

public class SubTask implements Runnable{
	
	private int n=5;
	

	@Override
	public void run() {
		
		while(true){
			
			System.out.println(" -------- SubTask -----------");
			
			//获取对象MainClient.Lock上的锁
			synchronized (MainClient.Lock) {
				
				if(!MainClient.notifyRun){
					try {
						MainClient.Lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					MainClient.notifyRun=true;
				}
				
				for(int i=1;i<=n;i++){
					System.out.println("SubTask run."+i);
				}
				
				
			    //本线程放入wait set,释放对象MainClient.Lock上的锁,让MainTask运行
			    MainClient.Lock.notifyAll();
			    MainClient.notifyRun=false;
			}
			
			
		}
		
		
	}

}

 

 

运行结果:

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

   

 

89、Java并发编程:生产者 - 消费者问题的解决方案 本文介绍了在Java并发编程中解决生产者-消费者问题的两种主要方式。第一种方式使用了ArrayBlockingQueue,这是一种线程安全的缓冲区实现,能够简化并发编程。第二种方式使用了synchronized关键字以及Object类的wait、notify和notifyAll方法,深入探讨了线程同步机制。文章还对两种实现方式进行了对比分析,并给出了注意事项,以帮助开发者更好地理解和应用线程同步技术。 阅读详情

相关推荐

纽马克-贝塔法(Newmark-Beta Method)在结构动力学中的应用与实现

本文深入解析了纽马克-贝塔法(Newmark-Beta Method)在结构动力学数值计算中的核心原理与应用。作为经典的时间积分算法,它通过调节γ和β参数,在计算精度、稳定性与效率间取得平衡,尤其适用于地震响应、风振分析等工程场景。文章详细阐述了其数学内核、在有限元分析中的实现步骤,并对比了隐式与显式方案的适用场景,为工程师提供了关键的方法选择与参数调优指导。

weixin_29232121的博客 148

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

1、wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。 2、wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。 3、 由于 wait()、notify/notifyAll() 在syn...

weixin_30827565的博客 728

STM32+ESP8266接入OneNet物联网平台全流程

MQTT协议是物联网设备与云平台通信的主流轻量级消息传输标准,其发布/订阅模型天然适配嵌入式资源受限场景;OneJSON作为中国移动OneNet平台定制的数据格式,在标准JSON基础上精简Schema、降低解析开销,显著提升STM32等MCU的处理效率。该技术组合兼顾安全性、低功耗与工程可量产性,广泛应用于环境监测、智能仪表、工业传感器等远程数据采集系统。实际落地需协同完成云平台物模型定义、Token动态认证、MQTT Topic严格构造、AT指令可靠交互及单总线传感器数据融合等关键环节。本文以DS18B2

u5v6w7的博客 1120

JAVA多线程之生产者与消费者问题

JAVA多线程之生产者与消费者问题 经典的“生产者与消费者”的问题实质上就是等待唤醒机制。 这里拿生产包子消费包子来说明等待唤醒机制如何有效利用资源: 包子铺线程生产包子,吃货线程消费包子。当包子没有时(包子状态为false),吃货线程等待,包子铺线程生产包子(即包子状态为true),并通知吃货线程(解除吃货的等待状态),因为已经有包子了,那么包子铺线程进入等待状态。接下来,吃货线程能否进一步执行...

weixin_43838446的博客 514

手把手教你设计2bit反射型超表面:从单patch扫参到pin管配置全流程

本文提供了一份2bit反射型超表面设计的完整工程实践指南。从单贴片谐振器的参数化扫描与“270度法则”应用,到PIN二极管等效电路模型的获取与集成,再到利用参数化扫描高效仿真四种工作状态,手把手指导读者完成从单元设计到阵列布局、偏置线集成及加工考量的全流程,旨在帮助射频工程师将概念转化为可加工测试的实体模型。

java5的博客 1023

Arcgis中的模型构建器(ModelBuilder)技术之批量图层转KML

这段时间全省各地都在开展耕地流出图斑整改恢复工作,期间或多或少都需要村委会协助摸排举证,除了举证软件外,奥维、外业精灵等软件想必大家接触得也很多。这就经常需要我们转kmz文件给业主或者摸排人员,那么有没有什么方法在arcgis下快速批量转kmz文件呢,今天就介绍一下如何在模型构建器(ModelBuilder)构建批量图层转KML的模型。

weixin_44671081的博客 1325

JDK源码系列:synchronized与wait、notify、notifyAll

大家好,今天聊一聊synchronized与obj.wait()、obj.notify()、obj.notifyAll() 之间的关系以及它们的实现原理。我们今天采用边写demo边分析的方式来进行。案例1:public class SyncDemo { public synchronized int add(int a,int b){ ...

super_scan的专栏 473

Aurix TC3xx系列MCU DMA模块配置方法(二)

本文主要基于英飞凌Aurix TC3xx系列MCU,通过EB tresos配置工具,介绍DMA驱动模块的配置方法。

m0_38045338的博客 2851

为什么wait,notify和notifyAll要与synchronized一起使用?

Object.wait(),Object.notify(),Object.notifyAll()都是Object的方法,换句话说,就是每个类里面都有这些方法。 Object.wait():释放当前对象锁,并进入阻塞队列 Object.notify():唤醒当前对象阻塞队列里的任一线程(并不保证唤醒哪一个) Object.notifyAll():唤醒当前对象阻塞队列里的所有线程 为什么这三个...

Crazy.Mark 8979

PCIe 互联的芯片-- P2P(Peer-to-Peer)

PCIe设备间支持P2P直连通信,但需满足硬件、固件和软件三方面条件。硬件需CPU/芯片组和PCIe交换器支持P2P,BIOS需开启相关设置,操作系统和驱动也要适配。消费级GPU通常禁用此功能,且PCIe P2P性能(128GB/s带宽)远低于NVLink(900GB/s)。常见限制包括ACS阻断、IOMMU隔离和带宽瓶颈。可通过nvidia-smi或NCCL测试验证P2P是否生效。该技术适合异构设备通信,但需注意配置调优。

MHD0815的博客 683

“华为杯”研究生数学建模竞赛2016年-【华为杯】A题:多无人机协同任务规划

题分别求解,保证了攻击方无人机滞留在防御方雷达有效探测范围内的时间总和最小,接着,通过提出巡检待命无人机的设想,型无人机携带炸弹的具体清单和攻击的目标清单),保证攻击方的无人机滞留防御方雷。在使用基于贪心算法的覆盖法时,覆盖的目标点中必须首先不含配备雷达站的目标点。步优化保证攻击方的无人机滞留防御方雷达有效探测范围内的时间总和最小,需首先。的“灵巧”炸弹,采用抛投方式对地攻击,即投放后炸弹以飞机投弹时的速度作抛物。运动,当炸弹接近目标后,可主动寻的攻击待打击的目标,因此炸弹落点位于目标中。

getusushu的博客 1037

为什么wait,notify和notifyAll要与synchronized一起使用?为什么要放在Object类里面

目录 为什么wait,notify和notifyAll要与synchronized一起使用? wait()和notify()是Object的成员函数,是基础中的基础。为什么Java要把wait()和notify()放在如此基础的类里面,而不是作为像Thread一类的成员函数,或者其他类的成员函数呢? 为什么wait,notify和notifyAll要与synchronized一起使用? Object.wait(),Object.notify(),Object.notifyAll()都是Obje.

libufan的博客 379

Virtuoso 中的tech file 详细说明

工艺文件(Techfile)是集成电路设计中的核心配置文件,定义了从晶圆制造到版图验证全流程所需的工艺规则和图层属性。在Cadence Virtuoso平台中,Techfile作为连接设计与制造的桥梁,主要包含以下内容: 图层体系定义 金属层、介质层、多晶硅层等物理图层的编号、名称和显示属性 图层用途(DRAW、MASK等)及图层-用途组合(LPP)的优先级 设计规则约束 几何尺寸规则(最小线宽/间距) 包围和延伸规则 密度规则和特殊工艺规则(如天线效应) 器件定义 MOS管、电阻等器件的图层构成 电学参数

u013620135的博客 8132

JVM源码分析之Object.wait/notify(All)完全解读

概述 本文其实一直都想写,因为各种原因一直拖着没写,直到开公众号的第一天,有朋友再次问到这个问题,这次让我静心下来准备写下这篇文章,本文有些东西是我自己的理解,比如为什么JDK一开始要这么设计,初衷是什么,没怎么去找相关资料,所以只能谈谈自己的理解,所以大家看到文章之后可以谈谈自己的看法,对于实现部分我倒觉得说清楚问题不大,code is here,看明白了就知道怎么回事了。 Object.wait/notify(All)大家都知道主要是协同线程处理的,大家用得也很多,大概逻辑和下面的用法差不多 .

weixin_39363245的博客 186

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

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

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java并发编程(实战):用“等待-通知”机制优化循环等待(1)

等待 - 通知机制是一种非常普遍的线程间协作的方式。工作中经常看到有同学使用轮询的方式来等待某个状态,其实很多情况下都可以用今天我们介绍的等待 - 通知机制来优化。Java 语言内置的 synchronized 配合 wait()、notify()、notifyAll() 这三个方法可以快速实现这种机制,但是它们的使用看上去还是有点复杂,所以你需要认真理解等待队列和 wait()、notify()、notifyAll() 的关系。最好用现实世界做个类比,这样有助于你的理解。

2401_84048445的博客 1046

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

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

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java等待-通知机制

Java等待-通知机制 现实世界中的就医流程拥有着完善的等待 - 通知机制,对比该就医流程能更好的理解和应用并发编程中的等待 - 通知机制。 基本就医流程: 患者去挂号,然后到就诊门口分诊,等待叫号。 叫到自己号时,可以找大夫就诊(获取到锁)。 就诊过程中医生可能会让患者去做检查,同时叫下一位患者(不满足条件释放锁,线程进入等待状态)。 当患者做完检查后,拿报告重新分诊等待叫号(满足条件等待获取锁)。 当大夫再次叫到号时患者再去找大夫就诊(获取到锁)。 用synchronized实现等待 -

qq_35608927的博客 188

【高并发】面试官:讲讲高并发场景下如何优化加锁方式?

写在前面很多时候,我们在并发编程中,涉及到加锁操作时,对代码块的加锁操作真的合理吗?还有没有需要优化的地方呢?问题阐述产生死锁时的四个必要条件,只有四个条件同时具备时才能发生死锁。其中...

HollisChuang's Blog 597

关于java中的synchronized、wait以及notify和notifyAll

1.java中多线程同步方法有很多种,可以使用

_刘振华_的专栏 2144

Java synchronized中的wait/notify机制详解

Java synchronized中的wait/notify机制是基于对象监视器锁实现的线程通信方式。wait()会释放锁并使线程进入等待状态,notify()随机唤醒一个等待线程,notifyAll()唤醒所有线程。使用时必须在同步块内调用,并通过循环检查条件来避免虚假唤醒。该机制适用于生产者-消费者等模式,但要注意IllegalMonitorStateException和丢失唤醒等问题。相比Java 5的Condition接口,wait/notify更简单但不支持多条件。正确使用这一机制是编写可靠并发程

weixin_47242663的博客 1140

Java线程同步 (synchronized wait notify)

注:wait notify 都是Object的方法 同步(阻塞) :是一种防止对共享资源访问导致的数据不一致的一种模式。详细请参看操作系统。在Java中,由于对多线程的支持,对同步的控制主要通过以下几个方法,synchronized,和wait(),notify()和notifyAll(),下面进行一一的讲解:A关键字synchronized每个java对象都有

魏照哲的专栏 5万+

Thread_wait、notify、notifyAll的使用方法

wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。 这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。 •如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。 •如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。

qaz13177_58_的专栏 2万+

Java并发-synchronized与wait和notify

synchronized与wait和notifywait和notify/notifyAll基本使用synchronized同步代码块同步方法(静态与非静态)synchronized、wait、notify/notifyAll的底层实现 wait和notify/notifyAll基本使用 在调用wai方法时,线程必须要持有要对象的锁,当调用wai方法后,线程就会释放掉该对象的锁(monitor)。 在调用Thread类的sleep方法时,线程是不会释放掉对象的锁的。 当调用wait时,首先需要确保调用了wa

unicorn_code的博客 629

synchronized、wait、notify、notifyAll

因为同一个进程的线程之间可以共享同一个进程空间,所以实现线程的数据共享是很容易的(当然在并发中实现数据结构的一致性则另当别论),也可以使用管道流来进行线程通信(没必要)。此处只说协调控制机制 synchronized、wait、notify、notifyAll 使用Java语言内置关键字synchronized来进行加锁,可以保证任务执行的可见性和原子性,从而实现同步执行。synchroniz

蚂蚁的博客 509

synchronized静态代码块,以及其中的wait,notify和notifyAll

接触Java多线程这么久了,synchronized静态代码块以及其中的wait和notify方法一直没搞懂,网上关于此,不是旁敲侧击,就是晦涩难懂(我理解能力有限),实在无语了。今天把Java的源码导入到了eclipse,从源码中看到了我想要的答案。即本文专注于讲解透彻地讲解synchronized代码块,wait以及notify的使用方法,绝对一针见血,绝不旁敲侧击,没意思。注:本文不会讲什么是

企鹅肖 2117
上一篇: 如何避免BUG,这个问题头疼
下一篇: java并发 locks包:Condition(二)
liyebing
博客等级 码龄20年 32粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值