JAVA多线程-Object.wait(),Object.notify(),Object.notifyAll()

Object 中的 wait() 与 notify() 方法有什么用? wait()方法和notify()方法是用于线程间的通信和同步的方法。由于线程之间是抢占式执行的,因此线程之间执行的先后顺序难以预知。但是有时候我们希望合理的协调多个线程之间的执行顺序。这时候就需要用到 Object 中的 wait()方法和notify()方法了。 阅读详情

初步理解

wait()

  1. 使线程停止运行,进入等待队列,会立刻释放对象锁。
  2. wait(0) 代表的是无限期的等待,不能自动唤醒。
  3. java.lang.Object类方法。

notify()

  1. 唤醒一个正在等待当前对象的waiting线程,遵循FIFO(先进先出)策略。
  2. notify()调用后,并不是马上就释放对象锁,而是在相应的synchronized{…}语句块执行结束后,自动释放锁后,JVM在wait()对象锁的线程中随机选取一线程赋予其对象锁,唤醒线程,继续执行。这样就提供了在线间同步、唤醒的操作。
  3. java.lang.Object类方法。

notifyAll()

  1. 唤醒正在等待当前对象的所有等待线程。
  2. 默认的唤醒策略是:LIFO(后进先出)。
  3. java.lang.Object类方法。

wait()与notify()

  1. Obj.wait(),与Obj.notify()必须与synchronized(Obj)一起使用,也就是wait()是针对已经获取了Obj锁进行操作。
  2. 从语法角度来说就是Obj.wait(),Obj.notify()必须在、synchronized(Obj){…}语句块内。
  3. 从功能上来说wait就是指在该线程获取对象锁后,主动释放对象锁,同时本线程休眠。notify()就是对对象锁的唤醒操作。

wait()与sleep()
共同点

  1. 都可以指定线程阻塞的时间。
  2. 都可以通过interrupt()方法打断(不建议使用)线程的暂停状态 ,从而使线程立刻抛出InterruptedException。如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep /join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。
    需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。

不同点

  1. sleep()是Thread类的方法,wait()是Object类的方法。
  2. sleep()方法没有释放锁,而wait()方法释放了锁。
  3. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。

执行notify()后,waiting线程可能的状态

线程a先抢到了对象o的锁,然后wait,然后b抢到了o的锁,然后b中调用o.notify并释放锁,此时a是running状态还是blocked状态??
如果b在执行完notify()后没有释放锁则线程a是阻塞等待,
如果线程b执行完同步代码块(释放锁)后,则线程a就是就绪态,不一定是运行态

代码实操,三线程打印ABC

建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。

public class T08WaitNotify {

    class T implements Runnable{
        // 自定义线程名称
        private String name;
        // 前一个obj
        private Object prev;
        // 当前obj
        private Object self;

        T(String name, Object prev, Object self){
            this.name = name;
            this.prev = prev;
            this.self = self;
        }

        @Override
        public void run() {
            int count = 0;
            while (count < 10) {
                synchronized (prev) {
                    synchronized (self) {
                        System.out.print(name);
                        count++;
                        self.notify();
                    }
                    try {
                        prev.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    }

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

        T08WaitNotify obj = new T08WaitNotify();

        Object oa = new Object();
        Object ob = new Object();
        Object oc = new Object();

        T a = obj.new T("A", oc, oa);
        T b = obj.new T("B", oa, ob);
        T c = obj.new T("C", ob, oc);

        Thread ta = new Thread(a);
        Thread tb = new Thread(b);
        Thread tc = new Thread(c);

        ta.start();
        Thread.sleep(1000); // 确保按照A、B、C顺序执行
        tb.start();
        Thread.sleep(1000);
        tc.start();
        Thread.sleep(1000);
    }
}

代码流程说明
A线程启动,依次取得c、a锁,打印A,执行notify()唤醒任意一个a对象等待池中的线程,待synchronized(self){}块执行完后释放a锁,执行wait(),将A线程放入c对象相关的等待池中等待被唤醒,同时释放c锁; 1秒后,B线程启动,依次取得a、b锁,打印B,执行notify()唤醒任意一个b对象等待池中的线程,待synchronized(self){}块执行完后释放b锁,执行wait(),将B线程放入a对象相关的等待池中等待被唤醒,同时释放a锁;1秒后,C线程启动,依次取得b、c锁,打印C,执行notify()唤醒任意一个c对象等待池中的线程(此时A线程被唤醒),待synchronized(self){}块执行完后释放c锁,执行wait(),将C线程放入b对象相关的等待池中等待被唤醒,同时释放b锁。

至此,完成一次ABC的打印。继续执行,从A线程开始,执行各自线程中的下一次循环。

特别说明
Java源码中wait()默认调用的是wait(0),表明线程无限等待,只能被其他线程唤醒。

参考
https://blog.youkuaiyun.com/u010002184/article/details/82912225
https://blog.youkuaiyun.com/hj1997a/article/details/84284973

【Java基础知识 21】java object类 Java基础教程系列(入门篇),打造精品专栏。 阅读详情

相关推荐

【数据分享】中国371个城市的坡度矢量数据和excel数据

在城市发展的进程中,地形地貌始终是影响规划决策的关键因素,而坡度作为表征地表倾斜程度的核心指标,更是贯穿于城市建设、生态保护等诸多环节。本文将全面解读中国 371 个城市坡度数据的相关情况,包括数据概况、生成流程、应用场景等内容,为读者呈现一份详尽的坡度数据指南。

qq_39719713的博客 1844

java JUC 中 Object里wait()、notify() 实现原理及实战讲解

在多核环境下,多个线程有可能同时执行monitorenter指令,并获取lock对象关联的monitor,但只有一个线程可以和monitor建立关联,这个线程执行到wait方法时,wait方法会将当前线程放入wait set,使其进行等待直到被唤醒,并放弃lock对象上的所有同步声明,意味着该线程释放了锁,其他线程可以重新执行加锁操作,notify方法会选择wait set中任意一个线程进行唤醒,notifyAll方法会唤醒monitor的wait set中所有线程。4、最终底层的park方法会挂起线程。

LoveSummer 5万+

TCP协议中ARQ自动重传的三种实现方式对比(含SACK详解)

本文深入解析TCP协议中ARQ自动重传的三种实现方式,包括停止-等待、回退N步和选择重传协议,特别详细介绍了SACK机制的工作原理和优势。通过对比分析各协议的效率、复杂度和适用场景,为网络通信中的可靠性传输提供了实用的选型指南。

weixin_30776273的博客 461

Object类九大方法之wait方法

Object类九大方法之wait方法 wait、notify和notifyAll方法是Object类的final native方法。所以这些方法不能被子类重写,Object类是所有类的超类,因此在程序中有以下三种形式调用wait等方法。 wait();//方式1: this.wait();//方式2: super.wait();//方式3 void notifyAll() 解除所有那些在该...

TimeFriends 6563

KEGG两类报错--①No gene can be mapped--②URL ‘https://rest.kegg.jp/link/hsa/pathway‘…

版本问题,重新安装一下clusterProfiler包。网络问题,可以等待之后再试一下(试过不是)(以上可以排除基因不存在的错误因素)

weixin_57699783的博客 2万+

易智联LM401模块学习(一)——初识Lora

Lora

weixin_46046597的博客 1054

Object.wait

Object.wait 功能:挂起当前线程并释放锁 用途:用于多线程开发,主要用于条件队列编程。 用法:线程获取object锁后,调用object.wait,该线程被系统挂起,并释放锁。通过调用object.notify或者object.notifyAll可以唤醒该线程(调用notify或者notifyAll之前必须获得object锁) 唤醒:1,notify notifyAll

wk022的专栏 1172

RLC电阻电容电感基础知识——电感篇

电感 等效电路 电感线圈由铜导线绕制,等效电路如图所示。 寄生电阻RS,包括了绕线电阻、引脚串联电阻以及磁芯损耗电阻三部分组成,其中绕线电阻与线径、长度、铜线电阻率有关;引脚电阻与引线长短、粗细有关;磁芯损耗电阻与磁芯材料特性有关,显然磁芯损耗电阻还与工作频率有关.寄生电容C主要是绕线圈与圈之间的杂散电容(为PF级),与绕线工艺有关。 等效导纳 显然: (1)当角频率ω(频率f)较小时,呈电感性. (2)当角频率ω等于ω0时,导纳Y虚部为0,呈现电阻性,即发生共振。令导纳Y虚部为0,即可求出共振角频率ω

azj2019的博客 1万+

13. 大佬问我: notify()会立刻释放锁么?

大佬问我: notify()会立刻释放锁么? ​ 我的内心戏: 肯定会啊! 这么简单的问题? 聪明如我, 决定装小白, 回答: 不会? 大佬: 很好, 小伙子基础不错! 我: 大佬: 说说为什么 我: ……………… 于是, 有了这篇文章! 问题的根本原来在于 “立刻”这个描述词! 如果你和咸鱼君一样懵逼, 不妨往下看! 技术大佬可以告辞了!! 接下来, 我们深入的分析分析wait和notify 前言 前面介绍了Synchronized关键词的原理与优

CTO技术的博客 1504

华为OD机试2025C卷真题题库目录|机考题库 + 算法考点详解

本文整理华为OD 2025C卷 机试(机考)题库,提供高频考点精析与详细题目内容,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

qq_45776114的博客 3982

[ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341)

[ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341) Drupal是使用PHP语言编写的开源内容管理框架(CMF),它由内容管理系统(CMS)和PHP开发框架(Framework)共同构成,在GPL2.0及更新协议下发布。Drupal在某些情况下,通过文件模块或者子系统上传恶意文件触发XSS漏洞。

qq_51577576的博客 2207

Java 多线程学习(8)Object.wait()、Object.notify() 和 Object.notifyAll()

深入的学习一下 Object 对象中所提供的 wait、notify 和 notifyAll 方法。

HappyFeet的博客 529

Buildroot RK3568系统中更改GPU驱动为:panfrost

1:Kernel中开启Panfrost 2:更新mesa 到mesa-24.0.2 3:查看/proc/interrupts 中的panfrost 中断 4:LInux启动日志 5:查看GPU负载

OpenWrt/WLAN/驱动/Android/嵌入式开发总结 2078

wait()、notify()和notifyAll()方法为什么属于Object

前提条件 要搞清这个问题,我们首先需要知道wait()、notify()和notifyAll()是干吗的,然后才能够知道它们为什么属于Object。就以wait为例吧,wait的含义是使当前线程放弃对象锁,并进入阻塞状态。 原因 原因一:Java中,任何对象都可以作为锁,既然wait是放弃对象锁,当然就要把wait定义在这个对象所属的类中。更通用一些,由于所有类都继承于Object,我们完全可以...

记录日常的点点滴滴 5348

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Object.wait()与Object.notify()的用法

转自 http://www.cnblogs.com/xwdreamer/archive/2012/05/12/2496843.html object.wait()和object.notify()和object.notifyall() object.wait()方法:让拥有object对象的锁的线程进入等待状态,并释放对象锁。  object.wait()和object.notif

九天之凤 636

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

《JAVA》多线程中wait,notify,notifyAll使用小结

在Java的Object类中有三个final的方法允许线程之间进行资源对象锁的通信,他们分别是: wait(), notify() and notifyAll()。调用这些方法的当前线程必须拥有此对象监视器,否则将会报java.lang.IllegalMonitorStateException异常。waitObject的wait方法有三个重载方法,其中一个方法wait() 是无限期(一直)等待,直...

CallmeZhe的博客 470

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Java-Object-wait-notify-notifyAll

使当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。换句话说,该方法的行为就像简单地调用wait(0)。当前线程必须拥有该对象的监视器。线程释放该监视器的所有权,并等待,直到另一个线程通过调用notify方法或notifyAll方法来通知等待该对象监视器的线程唤醒。。和都是可能发生,因此应当在循环中使用该方法:while (<条件不成立>)obj.wait();... //根据条件执行适当的操作此方法只能由拥有该对象监视器的线程调用。

Java程序员的知识博客 1256

java并发多线程通信—wait()、notify()、notifyAll()、join()

wait() ,notifyAll(),notify() 三个方法都是Object类中的方法。假如有一个对象锁Documentwait(): 调用该方法的线程进入WAITING状态,并将当前线程放置到对象的等待队列,只有等待另外线程的通知(notify)或被中断才会返回,需要注意,调用wait()方法后,会释放对象的锁。notify(): 通知一个在对象上等待的线程,由WAITING状态变为BLOCKING状态,可以参考下图,从等待队列移动到同步队列,等待CPU调度获取该对象的锁,当该线程获取到了对象的锁后

进击的豌豆的博客 512

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

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

一只苟延残喘的卑微蝼蚁 371

Java多线程wait()、notify()、notifyAll()

一、功能介绍 1.wati():调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁) 2.notify():调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程; 3.notifyAll():调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程; 二、注意事项 1.这三个方法都是Object类中的方法,不是Thread类中的方法 2

qq_40478534的博客 197

Java多线程中wait, notify and notifyAll的使用

在Java的Object类中有三个final的方法允许线程之间进行资源对象锁的通信,他们分别是: wait(), notify() and notifyAll()。 调用这些方法的当前线程必须拥有此对象监视器,否则将会报java.lang.IllegalMonitorStateException exception异常。

阳光日志 2万+

Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法

在Java的Object类中包含了3个final的方法,这三个方法允许线程来交流资源是否被锁定。这三个方法就是wait(),notify()以及notifyAll().在对象上调用这三个方法的线程需要包含一个对象监视器(锁),否则就会抛出java.lang.IllegalMonitorStateException异常。wait方法对象的wait方法由三个,一个是令对象等待任何线程来调用notify或

EthanPark的博客 2020

Java中wait()方法和notify()/notifyAll()

Java中wait()方法和notify()/notifyAll()

QYgujingjing的专栏 494

为什么wait, notify 和 notifyAll这些方法不在thread类里面?

因此,它们被定义在 `Object` 类中,因为所有的 Java 对象都可以作为锁,并且每个对象都有与之相关联的等待队列(wait set)和通知队列(notify set)。`wait()`、`notify()` 和 `notifyAll()` 方法是对象级别的方法,它们不是 `Thread` 类的方法,而是定义在 `Object` 类中的。由于每个对象都有这些队列和相关的同步机制,因此这些方法是定义在 `Object` 类中的,而不是 `Thread` 类中。

NZC2237的博客 791

java线程间同步----wait、notify、synchronized

java wait notify synchronized 详解

qq_41768644的博客 733
上一篇: Java多线程-基础篇
下一篇: Linux上Python3使用smtp发送邮件
松林羊
博客等级 码龄11年 43粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值