【JavaEE】多线程(3) -- 线程等待 wait 和 notify

目录

1. wait()⽅法

2. notify()⽅法

3. notifyAll()⽅法

4. wait 和 sleep 的对⽐(⾯试题)


由于线程之间是抢占式执⾏的, 因此线程之间执⾏的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执⾏先后顺序.

完成这个协调⼯作, 主要涉及到三个⽅法

  • wait() / wait(long timeout):  让当前线程进⼊等待状态.
  • notify() / notifyAll():  唤醒在当前对象上等待的线程.

注意: wait, notify, notifyAll 都是 Object 类的⽅法

1. wait()⽅法

wait 做的事情:

• 使当前执⾏代码的线程进⾏等待. (把线程放到等待队列中)

• 释放当前的锁

• 满⾜⼀定条件时被唤醒, 重新尝试获取这个锁.

wait 要搭配 synchronized 来使⽤. 脱离 synchronized 使⽤ wait 会直接抛出异常.

wait 结束等待的条件:

• 其他线程调⽤该对象的 notify ⽅法.

• wait 等待时间超时 (wait ⽅法提供⼀个带有 timeout 参数的版本, 来指定等待时间).

• 其他线程调⽤该等待线程的 interrupted ⽅法, 导致 wait 抛出 InterruptedException 异常.

public class Test {
    public static void main(String[] args) {
        Object locker = new Object();
        Thread t = new Thread(()->{
            synchronized (locker) {
                System.out.println("wait 等待之前");
                try {
                    locker.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("wait 等待结束");
            }
        });

        t.start();
    }
}

这样在执⾏到 object.wait() 之后就⼀直等待下去,那么程序肯定不能⼀直这么等待下去了。这个时候就 需要使⽤到了另外⼀个⽅法唤醒的⽅法 notify()。

wait提供了两个版本:

2. notify()⽅法

notify ⽅法是唤醒等待的线程.

  • ⽅法notify()也要在同步⽅法或同步块中调⽤,该⽅法是⽤来通知那些可能等待该对象的对象锁的其 它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。
  • 如果有多个线程等待,则有线程调度器随机挑选出⼀个呈 wait 状态的线程。(并没有 "先来后到")
  •  在notify()⽅法后,当前线程不会⻢上释放该对象锁,要等到执⾏notify()⽅法的线程将程序执⾏ 完,也就是退出同步代码块之后才会释放对象锁

notify 其实可以不放到 synchronize 里, 不需要先加锁, 但是 java 中特别约定要把 notify 放到 synchronized 里. 

代码⽰例: 使⽤notify()⽅法唤醒线程

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object locker = new Object();
        Thread t1 = new Thread(()->{
            synchronized (locker) {
                System.out.println("t1 wait 之前");
                try {
                    locker.wait();
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t1 wait 之后");
            }
        });

        Thread t2 = new Thread(()-> {
            try {
                Thread.sleep(3000);
                //让 t1 线程有时间进入到wait状态
                synchronized (locker) {
                    System.out.println("t2 notify 之前");
                    locker.notify();
                    System.out.println("t2 notify 之后");
                }
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        t2.start();
    }
}

wait 和 notify 彼此之间是通过 Object 对象联系起来的, 必须是两个对象一致时才能够被唤醒.

3. notifyAll()⽅法

notify⽅法只是唤醒某⼀个等待线程. 使⽤notifyAll⽅法可以⼀次唤醒所有的等待线程.

理解 notify 和 notifyAll

notify 只唤醒等待队列中的⼀个线程. 其他线程还是乖乖等着

notifyAll ⼀下全都唤醒, 需要这些线程重新竞争锁

4. wait 和 sleep 的对⽐(⾯试题)

1. wait 需要搭配 synchronized 使⽤. sleep 不需要.

2. wait 是 Object 的⽅法 sleep 是 Thread 的静态⽅法.

在Java中,wait()sleep()都是用于线程控制的方法,但是它们有一些重要的区别。

  1. wait()是Object类中定义的方法,而sleep()是Thread类中定义的方法。wait()是在对象级别上进行操作,而sleep()是在当前线程级别上进行操作。

  2. wait()方法会释放线程持有的锁,使线程进入等待状态,直到其他线程调用相同对象上的notify()notifyAll()方法来唤醒等待的线程。sleep()方法不会释放线程持有的锁。

  3. wait()方法必须在同步上下文中被调用,即在同步方法或同步块中,否则会抛出IllegalMonitorStateException异常。而sleep()方法可以在任何地方调用。

  4. wait()方法还可以指定一个超时时间,在等待超时后会自动唤醒线程。而sleep()方法只能通过interrupt()方法或等待指定时间来唤醒线程。

总的来说,wait()方法用于线程间的协调和通信,而sleep()方法主要用于线程的休眠。wait()方法在等待期间会释放锁,而sleep()方法不会释放锁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/213066.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

树莓派4B机器狗的串口通信驱动库pyserial实践

pyserial是一个串口通信驱动库,常用的Windows、Linux、MacOS等都可以安装,这里我使用的是树莓派4B来测试,这块板子还是很强大的,我们可以通过pyserial这个库来操作基于这块板子上的机器狗之类的设备。 1、四足机器狗 本人的是四…

初识Java 18-6 泛型

目录 潜在类型机制 支持潜在类型机制的语言 Python的潜在类型机制 C的潜在类型机制 Java中的直接潜在类型机制 潜在类型机制的替代方案 反射 将方法应用于序列中的每个元素 Java 8的潜在类型机制(间接实现) 潜在类型机制的使用例(S…

条款2:不要滥用宏

文章目录 优先选择编译器而不是预编译器两种特殊情况使用宏替代函数调用总结 优先选择编译器而不是预编译器 假设我们预定义了一个宏#define ASPECT_RATIO 1.653,当我们的程序在这个地方出现错误的时候。可能会出现以下的问题: 符号名称ASPECT_RATIO可能…

MQTT客户端、代理(broker)和连接建立

在前篇文章(http://t.csdnimg.cn/IamPz)中,介绍了发布/订阅架构和MQTT如何据此交换信息,其中的关键概念是: 发布/订阅架构触耦了负责发布信息的客户端(发布者)和负责接收信息的客户端&#xff…

C语言-联合和枚举

------------------------------------ --------------- ------ 最慢的步伐不是跬步,而是徘徊; 最快的脚步不是冲刺,而是坚持。 今天来到我们的联合和枚举类型的讲解: 目录 联合体类型 联合体类型的声明 联合体类型的特点 …

Wireshark抓包分析RTMP协议时,出现Unknown问题

进行rtmp推流时,使用wireshark抓包,发现部分包显示Unknown 解决方法: 编辑 -> 首选项 -> Protocols -> RTMPT,这里Maximum packet size默认是32768 将该值调大,比如调成1048576,即可解决该问题。…

ChatGPT 的 18 种玩法,你还不会用吗?

你确定,你会使用 ChatGPT 了吗? 今天给大家整理了 18 种 ChatGPT 的用法,看看有哪些方法是你能得上的。 用之前我们可以打开R5Ai平台,可以免费使用目前所有的大模型 地址:R5Ai.com 语法更正 用途:文章…

改进LiteOS中物理内存分配算法(详细实验步骤+相关源码解读)

一、实验要求 优化TLSF算法,将Best-fit策略优化为Good-fit策略,进一步降低时间复杂度至O(1)。 优化思路: 1.初始化时预先为每个索引中的内存块挂上若干空闲块,在实际分配时避免分割(split)操作&#xff…

[原创]C++98升级到C++20的复习旅途-从汇编及逆向角度去分析“constexpr“关键字

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XXQQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi…

AtCoder Beginner Contest 331 题解 A-E

目录 A - TomorrowB - Buy One Carton of MilkC - Sum of Numbers Greater Than MeD - Tile PatternE - Set Meal A - Tomorrow 原题链接 题目描述 已知一年有M个月D天,求出第y年m月d天的后一天是哪一天。 思路:分类讨论 分别讨论m和d的是否是最后一个月…

基于SpringBoot的旅游信息网【源码好优多】

简介 旅游信息网是一款介绍旅游相关内容的网站,分为前台和后台部分,其中前台用户注册以后可以浏览景点、景点详情、预订景点、酒店、车票、保险、以及浏览旅游攻略、个人信息修改、在线留言等,管理员在后台对景点、攻略、订单信息、酒店信息、…

oj赛氪练习题

数组调整 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int n scanner.nextInt();int k scanner.nextInt();int[] arr new int[n];for (int i 0; i < n; i) {arr[i] scanner.nextIn…

java源码-类与对象

1、面向对象与面向过程 在了解类和对象之前我们先了解一下什么是面向过程和面向对象。 1&#xff09;面向过程编程&#xff1a; C语言就是面向过程编程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 2&#xff09;面向对…

Redis 发布订阅机制深入探索

Redis 的发布订阅&#xff08;pub/sub&#xff09;机制是一种消息传递模式&#xff0c;允许消息的发送者&#xff08;发布者&#xff09;和消息的接收者&#xff08;订阅者&#xff09;通过一个中介层&#xff08;频道&#xff09;进行通信&#xff0c;而无需彼此直接交互。以下…

半导体工艺发展概述

集成电路发展到今天&#xff0c;经历从1940年的PN结发现&#xff0c;到1950年BJT三极管发明&#xff0c;再到1963年CMOS电路发明。从单纯基于Si的半导体电路&#xff0c;再到GaAs, GaN&#xff0c;SiGe, InP等化合物半导体集成电路。不断的通过化学材料配比&#xff0c;基本单元…

TinyVue 组件库助力赛意信息获得工业软件种子奖

首先恭喜广州赛意信息科技股份有限公司荣获工业软件种子奖&#xff01;在本次大赛中&#xff0c;凭借“数据驱动智造&#xff0c;基于 iDME 的赛意新一代 SMOM 赋能电子行业制造运营管理解决方案”这一作品脱颖而出~ 大赛简介 10月30日至10月31日&#xff0c;由广东省工业和信…

圆通速递查询入口,以表格的形式导出单号的每一条物流信息

批量查询圆通速递单号的物流信息&#xff0c;以表格的形式导出单号的每一条物流信息。 所需工具&#xff1a; 一个【快递批量查询高手】软件 圆通速递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;并登录 步骤2&#xff1a;点击…

Hadoop——分布式计算MapReduce和资源调度Yarn

分布式计算 MapReduce YARN架构 YARN集群部署 一、Hadoop安装目录下/etc/hadoop修改mapred-env配置文件&#xff0c;mapred-site.xml文件 二、etc/hadoop文件内&#xff0c;修改yarn-env.sh&#xff0c;yarn-site.xml 三、将配置好的文件分发到其他服务节点 start-dfs.…

SLAM ORB-SLAM2(10)轨迹跟踪过程

SLAM ORB-SLAM2(10)轨迹跟踪过程 1. 总体过程2. ORB 特征点提取2.1. 相机数据处理2.1.1. 单目相机图像处理2.1.2. 双目相机图像处理2.1.3. RGBD相机图像处理2.2. ORB 特征点3. 地图初始化3.1. 坐标形式3.2. 坐标原点3.3. 地图尺度4. 相机位姿初始估计4.1. 关键帧4.2. 运动模型…

文件搜索神器—Everything,结合内网穿透秒变在线搜索神器!

Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问 文章目录 Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 前…