多线程中的notify和wait方法的使用

多线程编程中的“等待和通知机制”:wait 和 notify 方法 介绍了由 wait 和 notify 方法组成的等待和通知机制。 阅读详情

Java线程同步中wait()和notify()简洁例子

搞懂这两个的用法之前,请你务必搞懂线程同步的道理,否则,下面这一大篇你应该是看不懂的。

wait()和notify()一系列的方法,是属于对象的,不是属于线程的。它们用在线程同步时,synchronized语句块中。

我们都知道,在synchronized语句块中,同一个对象,一个线程在执行完这一块代码之前,另一个线程,如果传进来的是同一个object,是不能进入这个语句块的。也就是说,同一个对象

是不能同时被两个线程用来进入synchronized中的。这就是线程同步。

废话不多说,先用通俗一点的语言来解释一下wait()和notify():

wait()意思是说,我等会儿再用这把锁,CPU也让给你们,我先休息一会儿!

notify()意思是说,我用完了,你们谁用?

也就是说,wait()会让出对象锁,同时,当前线程休眠,等待被唤醒,如果不被唤醒,就一直等在那儿。

notify()并不会让当前线程休眠,但会唤醒休眠的线程。

先看第一个例子!

public class ThreadF {

public static void main(String[] args) {

final Object object = new Object();

Thread t1 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T1 start!");

try {

object.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("T1 end!");

}

}

};

Thread t2 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T2 start!");

object.notify();

System.out.println("T2 end!");

}

}

};

t1.start();

t2.start();

}

}

这第一个例子很简单,写了两个线程(分别是两个类,两个run方法)。

两个run方法之间没有关系,但是,他们都用了同一个object!

仔细看,T1里面主要写了个wait(),而T2里面主要写了个notify()。

我们看到执行结果是:

T1 start!

T2 start!

T2 end!

T1 end!

流程可以这样解释:

T1启动,让出锁,让出CPU,T2获得CPU,启动,唤醒使用了object的休眠的线程,T1被唤醒后等待启动,T2继续执行,T2执行完,T1获得CPU后继续执行。

值得一提的是,再强调一遍:

wait会让出CPU而notify不会,notify重在于通知使用object的对象“我用完了!”,wait重在通知其它同用一个object的线程“我暂时不用了”并且让出CPUT。

所以说,看上面的顺序,

T2 start!

T2 end!

是连续的,说明它并没有因调用了notify而暂停!

那么,如

果两个线程都写wait没有线程写notify会有什么现象呢?试一下就知道了。

结果是,

T1 start!

T2 start!

然后就是一直等待!

道理很显然,T1先启动,然后wait了,T2获得了锁和CPU,在没有其它线程与它竞争的情况下,T2执行了,然后也wait了。

在这里,两个线程都在等待,没有其它线程将它们notify,所以结果就是无休止地等下去!

至少说明了一点,wait后如果没有其它线程将它notify,是绝不可能重新启动的。不可能因为目前没有线程占用CPU,某一个正在等待的线程就自动重启。

下面,我再把它改一下,写四个线程,分别是

T1 wait()

T2 notify()

T3 notify()

T4 wait()

public class ThreadF {

public static void main(String[] args) {

final Object object = new Object();

Thread t1 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T1 start!");

try {

object.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("T1 end!");

}

}

};

Thread t2 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T2 start!");

object.notify();

System.out.println("T2 end!");

}

}

};

Thread t3 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T3 start!");

object.notify();

System.out.println("T3 end!");

}

}

};

Thread t4 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T4 start!");

try {

object.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("T4 end!");

}

}

};

t1.start();

t2.start();

t3.start();

t4.start();

}

}

首先,大家知道,线程启动的顺序,和代码的先后顺序,理论上是没有关系的!

比如我这儿写的是按T1-T2-T3-T4的先后顺序先后start(),但实际上谁先启动,是有一定几率的。

执行上面代码,有两种结果:

一种是刚好wait两次,notify两次,notify在wait之后执行,刚好执行完。

另一种是,也是刚好wait两次,notify两次,但是,notify在wait之前执行,于是,至少会有一个线程由于后面没有线程将它notify而无休止

地等待下去!

我摘选了两种情况的输出结果,仅供参考:

1、可以执行结束的情况:

T1 start!

T2 start!

T2 end!

T1 end!

T4 start!

T3 start!

T3 end!

T4 end!

执行流程是:

T1启动,wait,T2获得锁和CPU,T2宣布锁用完了其它线程可以用了,然后继续执行,T2执行完,T1被刚才T2唤醒后,等待T2执行完后,抢到了CPU,T1执行,

T1执行完,T4获得CPU,启动,wait,T3获得了锁和CPU,执行,宣布锁用完了,其它线程可以用了,然后继续执行,T3执行完,已经被唤醒并且等待已久的T4

得到CPU,执行。

2、不能执行结束,有线程由于没有其它线程唤醒,一直在等待中:

T1 start!

T2 start!

T2 end!

T1 end!

T3 start!

T3 end!

T4 start!

执行流程:

T1启动,wait,让出CPU和锁,T2得以启动。T2启动,并唤醒一个线程,自己继续执行。被唤醒的线程,也就是T1等待启动机会。

T2执行完,T1抢到了CPU,执行,并结束。

这时,只剩下T3和T4,在此时,两个线程的机会均等。

但是,T3抢到了CPU,于是它执行了,而且唤醒了线程,虽然此时并没有线程休眠。说白了,它浪费了一次notify。T3顺利执行完。

这时,终于轮到了T4,它启动了,wait了,但是,后面已经没有线程了,它的wait永远不会有线程帮它notify了!

于是,它就这么等着!

请仔细看执行流程,看懂,再自己做一下试验。

仔看看,你会看到,凡是当前线程的run方法里面写了notify,有了start马上就会end,而如果是写的wait,有了start,下一个绝对不是输出这个线程的end。

所以说,T2和T3由于是写的notify,它们的start和end总是成对出现。而T1和T4由于是写的wait,它们start后,下一个绝不可能是它的end。

最后再提醒一下,我们的wait和notify是针对同一个object的,而非线程。我们这一篇都在讲对象锁,而不是线程。

顺便说一下,如果没有线程在wait,调用notify是不会有什么问题的,就像这样:

public class ThreadG {

public static void main(String[] args) {

final Object object = new Object();

Thread t1 = new Thread() {

public void run()

{

synchronized (object) {

System.out.println("T1 start!");

object.notify();

System.out.println("T1 end!");

}

}

};

t1.start();

}

}

T1 start!

T1 end!


声明:二次转载,未发现原文链接地址!原著见谅。


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

相关推荐

自举电容的工作原理-3句话总结

1、一道面试题 照例,先抛出来一道面试题:“Buck电路的SW引脚通常会放置一颗小电容,这颗电容有什么用?”。这个问题问得比较细,非常考验被面试者的硬件基本功。 2、似懂非懂的答案 有小伙伴可能不太清楚这颗电容的作用,回答不上来。也有小伙伴脱口而出:自举电容,用来做升压的。但后面好像说不出来具体逻辑。 没具体了解过,答不上来,也没啥可惜的。但是了解过一点,但又似懂非懂的这种,给出的答案只是轻轻点水或者千篇一律,那无疑是错过了一个加分项。 3、异步Buck的自举环路组成 既然是针对Buck电路讲自举电容,前面

ltqdxl的博客 3万+

理解 JAVA线程同步及其中中wait()和notify()简洁例子

JAVA线程同步中wait()和notify()简洁例子   搞懂这两个的用法之前,请你务必搞懂线程同步的道理,否则,下面这一大篇你应该是看不懂的。 wait()和notify()一系列的方法,是属于对象的,不是属于线程的。它们用在线程同步时,synchronized语句块中。 我们都知道,在synchronized语句块中,同一个对象,一个线程在执行完这一块代码之前,另一个线程,如果传进来

fei_ing的专栏 944

IEEE Transaction期刊模板使用注意事项

本文将总结使用IEEE Transactions系列期刊的投稿模板时的一些注意事项,包括模板本身的使用规范、参考文献的正确格式等其他内容。

weixin_39529207的博客 2万+

wait和notify讲解,及3个线程搭配wait和notify连续输出10次ABC

使用synchronized、wait和notify。 三个线程t1、t2、t3分别循环打印10次A、B、C,

喜之郎cc果冻的博客 833

实测对比:DECIMER、Img2Mol、MolScribe,哪个化学结构识别工具更靠谱?

化学结构识别(CSR)工具的核心任务是将分子结构图像转换为SMILES(Simplified Molecular Input Line Entry System)表示。这一过程需要克服图像质量差异、绘制风格变化以及特殊基团识别等挑战。三款工具采用不同的技术路线:DECIMER:基于EfficientNetV2+Transformer架构,优势在于处理标准期刊文献中的分子图示Img2Mol。

weixin_32576389的博客 342

Coze智能体开发:如何搭建一个生成长文本的工作流

扣子工作流提供了流程定制化的能力,我们可以把长文生成的流程拆分为多个步骤,例如先通过大模型节点生成大纲、再使用循环节点依次扩写各个段落,最后将各个段落组合起来,从而实现长文生成流程。此工作流可适用于学术写作、商业报告、小说创作等多种场景。

王国平的博客 1789

Java多线程之wait和notify的使用

在前面我们已经介绍过了join()方法可以用来控制线程的执行顺序了,但是join()却只能让整个线程执行结束再去执行另外的线程。控制线程执行顺序的效果是有限的,因此又有了wait()和notify(),目的其实都是为了控制程序的执行顺序的。本篇博客就主要来介绍wait()和notify()的使用。wait()方法其实主要做三件事:①把当前线程放进等待队列中②释放锁③被其他线程唤醒时,尝试重新获取锁接下来看一段问题代码:System.out.println("wait()之前");

m0_64986499的博客 968

彻底摆脱文献只能读开头的痛苦!这款文献检索神器真能帮你跨越文献付费限制(附实操演示)

大家是不是有过这样的经历,好不容易通过关键词搜到了和自己主题高度相关的文献,想要快速获取文献信息,推进研究进度,却又因为付费或者需订阅才能下载PDF,而被劝退。粘贴完成后,点击搜索,搜索结果页面会显示这篇文献的相关信息,有的文献有“下载PDF”,有的文献则只有“求助PDF”,不管是哪种情况,直接点击进入;我这里点击的是“下载PDF”,接着它会跳转页面。我用 Book 学术下载过不少付费文献,实测下来 80% 左右的文献,都能通过它的求助方式成功获取到,只有少部分文献等待的时间会稍微久一些或者没办法下载。

qq_64378896的博客 162

java基础总结(二十四)--wait与notify使用实例

1wait(), notify(), notifyAll()等方法介绍 1.wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”) 2.notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒...

秋天的猿 701

【Neo4j × Python】基于知识图谱的电影问答系统(含问题记录与解决)附:源代码(含Bug解决)

此前,曾介绍过Neo4j的一些基础知识,本篇将在PyCharm中与Neo4j建立关联,从0到1实现一个基于知识图谱的电影问答系统,实现过程中,没有一帆风顺,而是遇到了一些问题,因此也包含问题的记录与解决。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 3165

数据服务:数据服务框架Magic-API 介绍及实践

接口快速开发框架 基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象即可完成常见的HTTP API接口开发 。在线页面快速开发平台 基于 vue 的在线页面快速开发平台,主要把所有的 vue 代码都改为在线配置,最终获得一个 json 格式的页面新一代爬虫平台 基于Java实现的新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。今天给大家安利一

GIS摆渡人 2063

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

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

玻璃汽水的博客 1804

【AI智能体】QClaw 对接GitHub处理自动化任务实战操作详解

QClaw 对接GitHub处理自动化任务实战操作详解

congge 4867

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

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

VIBE的博客 4248

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

多线程中的 wait 和 notify 方法

首先先讲一个现象:线程饿死.什么是线程饿死?假如线程1 调度到 cpu 获取到锁, 但它发现要执行的逻辑, 前提条件无法满足, 那么它就无法执行, 进而释放锁, 释放之后 它又和其他线程一起参与锁竞争,但是线程1 当前处于 Runnable 状态, 而其他线程处于BLOCKED状态, 其他线程需要先被系统唤醒,所以很大概率, 又是线程1 获取到锁. 那么如此反复, 就形成了线程饿死.为了避免这种情况, 就要使用 wait 和 notify 方法.

2201_75798628的博客 771

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【Java多线程】wait方法和notify方法

介绍wait方法和notify方法

chaodddddd的博客 1426

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

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

云泽野の编程日记 1776

【多线程】volatile 关键字、wait 和 notify方法详解

Java EE 中volatile关键字详解,保证内存可见性,禁止指令重排序,wait()和notify(),notifyAll()方法详解,wait和sleep方法的对比面试题

ZXT的博客 1577

Java多线程——wait和notify的正确使用方法

wait&sleep wait释放锁,sleep不释放 wait是Object的方法,sleep是线程的静态方法 wait需要和synchronized一起使用 wait和sleep之后,线程都处于TIME-WAITING状态 wait的线程处于与当前锁对象相关的waitset中 wait和sleep被Interrupte都会有InterruptedException notify obj.notify()随机叫醒一个与obj对象锁相关的waitset中的一个线程 obj.notif

保暖透气大裤衩LeoLee的博客 588

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

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

五道口 9733

<JAVAEE> 多线程4-wait和notify方法

wait方法,以及wait加锁特性,wait和join的区别,以及wait和sleep的区别,线程饿死:线程一直得不到cpu资源导致线程无法进行工作notify方法,以及notify的注意事项wait和notify的练习加深理解欢迎大佬留下三连!

2401_88480494的博客 736

多线程join,wait和notify方法的使用

Java线程

qq_52215881的博客 604

Java多线程——wait和notify方法作用,线程的状态

Java多线程——wait和notify方法作用,线程的状态。

Arya的博客,专注后端领域 1305

多线程之间的通信-wait方法和notify方法解析

死锁(deadLock): 有两个线程,A线程获取到a资源,B线程获取到b资源,每个线程都必须获取到a,b两个资源才可以继续往下执行,但在此种情况下,A线程和B线程都不愿意放开自己手中的资源,此为死锁。   wait方法 wait是object类中的方法,而且被fianl修饰。wait方法可以被所有的类所继承并且不能被重写。 wait方法会造成当前线程等待,直到有其他的线程调用同一对象的...

sinat_38142087的博客 389

java 多线程 notify_Java多线程:wait()和notify()方法详解

通过前面的内容我们知道,当一个线程正在执行某个对象中被synchronized关键字修饰的方法时,这个对象锁上,其他线程必须等到当前线程执行完后才能访问。这个整个过程可以用下图来表示一个正在运行的线程想要执行synchronized方法,必须要获得当前对象的锁,如果没有获得则当前对象的锁则会被阻塞在对象锁池当中,直到前一个线程释放了该对象锁,当前线程重新获取到对象锁时,线程恢复到可运行状态,当cp...

weixin_39846186的博客 334
上一篇: SAP 建立WebService
下一篇: input file上传图片
Footloose_
博客等级 码龄10年 254粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值