当前位置: 首页 > news >正文

Java wait() notify() join()用法讲解

一、wait()

1. 源码:在这里插入图片描述

实际调用本地方法
在这里插入图片描述

2. 作用

  • 释放当前锁,并让当前线程进入等待状态;timeoutMillis为等待时间,单位毫秒,如果为0则表示无限等待下去;
  • 该方法使用前提是:当前执行线程必须持有该对象的锁;
  • 该方法为Object对象方法,所有Java对象都能调用wait方法,因为所有对象都可以成为锁;

3. 示例

失败案例

package com.suo.javacode.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WaitJoinTest {static ExecutorService cached = Executors.newCachedThreadPool();static final String LOCK_A = "lock-a";static final String LOCK_B = "lock-b";public static void main(String[] args) throws InterruptedException {cached.execute(()->{synchronized (LOCK_A) {System.out.println("线程-"+Thread.currentThread().getName()+"开始执行");try {LOCK_B.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程-"+Thread.currentThread().getName()+"执行结束");}});cached.shutdown();}
}

以上代码运行报错:
在这里插入图片描述
可以看到虽然调用线程持有锁对象,但和调用wait的对象不一致,仍然会报错java.lang.IllegalMonitorStateException ; 如何正常运行呢?只要把LOCK_ALOCK_B统一即可

正确用法

package com.suo.javacode.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WaitJoinTest {static ExecutorService cached = Executors.newCachedThreadPool();static final String LOCK_A = "lock-a";static final String LOCK_B = "lock-b";public static void main(String[] args) throws InterruptedException {cached.execute(()->{synchronized (LOCK_A) {System.out.println("线程-"+Thread.currentThread().getName()+"开始执行");try {LOCK_A.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程-"+Thread.currentThread().getName()+"执行结束");}});cached.shutdown();System.out.println("主线程结束");}
}

这里能调用成功,因为当前执行线程,拿到了LOCK_A的锁;这里代码会一直等待下去,可以设置时间,等待指定时间后会自动唤醒;也可以使用notify()方法;

二、notify()

1. 源码:都是本地方法在这里插入图片描述

在这里插入图片描述

2. 作用

  • notify()唤醒任意一个当前锁对象上,处于等待状态的线程;线程被唤醒后开始竞争锁;
  • notifyAll() 唤醒当前锁对象上,所有处于等待状态的线程;被唤醒后开始竞争锁;
  • 使用前提与wait()方法相同,执行线程必须持有该对象的锁;

3. 示例

package com.suo.javacode.concurrent;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WaitJoinTest {static ExecutorService cached = Executors.newCachedThreadPool();static final String LOCK_A = "lock-a";static final String LOCK_B = "lock-b";public static void main(String[] args) throws InterruptedException {for(int i=0;i<3;i++) {cached.execute(()->{System.out.println("线程-"+Thread.currentThread().getName()+"开始执行并尝试获取锁");synchronized (LOCK_A) {try {Thread.sleep(1000);System.out.println("线程-"+Thread.currentThread().getName()+"进入等待并释放锁");LOCK_A.wait();System.out.println("线程-"+Thread.currentThread().getName()+"被唤醒同时拿到锁");} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程-"+Thread.currentThread().getName()+"执行结束释放锁");}});}Thread.sleep(10000);for(int i=0;i<3;i++) {synchronized (LOCK_A) {LOCK_A.notify();System.out.println("唤醒任一线程");}}//或者使用LOCK_A.notifyAll();cached.shutdown();System.out.println("主线程结束");}
}

执行结果:
在这里插入图片描述

三、Java源码中的实际使用join()

1. join源码

在这里插入图片描述
在这里插入图片描述
从源码可以看出,join利用了wait方法来实现;millis>0时,只要线程还在运行,就会进入wait,等待millis时间结束或者线程结束,方法才能结束;millis==0时,只要线程没有执行完毕就会一直处于等待状态;因为代码中有while循环,notify唤醒后,也会立即进入下一次wait(),直到线程运行结束或者等待时间到期;

2. 作用

  • 等待线程执行完成
  • 只有Thread对象有该方法

3. 示例

	public static void main(String[] args) throws InterruptedException {Runnable r = ()->{for(int i=0;i<10;i++) {System.out.println("线程-"+Thread.currentThread().getName()+":"+i);}};Thread t1 = new Thread(r);Thread t2 = new Thread(r);t1.start();t2.start();t1.join();System.out.println("主线程等待t1执行结束:"+System.currentTimeMillis());t2.join();System.out.println("主线程等待t2执行结束:"+System.currentTimeMillis());System.out.println("主线程结束");}
  • 以上示例代码中的线程池仅作为测试使用,绝对不能用于生产,避免出现OOM;
  • wait()和join()在实际使用中都需要设置时间,避免出现无法唤醒的状况,从而造成OOM;
  • 实际使用中推荐使用CountDownLatch来代替join,使用join时无法使用线程池;

四、sleep和wait的异同

  • 相同点:

    1. 都能让当前执行线程进入阻塞;
  • 不同点:

     1.  sleep是Thread独有的静态方法 ,wait所有对象都有该方法;2.  sleep必须设置时间,wait可以不设置,且wait可以被notify唤醒;3.  sleep没有使用前提,wait必须持有对象锁;4.  sleep不会释放执行线程持有的锁对象,wait会释放锁;
    

相关文章:

Java wait() notify() join()用法讲解

一、wait() 1. 源码&#xff1a; 实际调用本地方法 2. 作用 释放当前锁&#xff0c;并让当前线程进入等待状态&#xff1b;timeoutMillis为等待时间&#xff0c;单位毫秒&#xff0c;如果为0则表示无限等待下去&#xff1b;该方法使用前提是&#xff1a;当前执行线程必须持…...

新手注意事项-visual studio 来实现别踩白块儿

自己之前为了熟悉easyx练习过一个简单的项目&#xff0c;别踩白块儿&#xff0c;链接在这里&#xff0c;别踩白块儿&#xff0c;当时比较稚嫩&#xff0c;很多东西都不会&#xff0c;可以说是只知道最基本的语法&#xff0c;头文件都不知道&#xff0c;一个一个查资料弄懂的&am…...

【力扣】2810. 故障键盘 <模拟>

【力扣】2810. 故障键盘 你的笔记本键盘存在故障&#xff0c;每当你在上面输入字符 ‘i’ 时&#xff0c;它会反转你所写的字符串。而输入其他字符则可以正常工作。给你一个下标从 0 开始的字符串 s &#xff0c;请你用故障键盘依次输入每个字符。返回最终笔记本屏幕上输出的字…...

Docker desktop使用配置

1. 下载安装 https://www.docker.com/ 官网下载并安装doker desktop 2. 配置镜像 &#xff08;1&#xff09;首先去阿里云网站上进行注册&#xff1a;https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors &#xff08;2&#xff09;注册完成后搜索&#xff1a;容…...

第一百二十一天学习记录:线性代数:矩阵乘法运算(宋浩板书)

在编程和学习数据结构的过程中&#xff0c;发现有些算法会用到矩阵和矩阵的乘法运算&#xff0c;因此先将这一个知识点学习一下。 矩阵和行列式的区别 各种矩阵的概念 矩阵运算 乘法☆ 总结三条不满足...

模拟实现消息队列项目(系列3) -- 服务器模块(硬盘管理)

目录 前言 1. 创建项目 2. 创建核心类 2.1 Exchange 2.2 MSQueue 2.3 Binding 2.4 Message 3. 数据库设计 3.1 SQLite 配置 3.2 Mapper层代码实现 3.2.1 创建表操作 3.2.2 交换机 队列 绑定的增加和删除 3.3 实现DataBaseManager 3.4 DataBaseManager单元测试 4.…...

【iOS】锁

线程安全 当一个线程访问数据的时候&#xff0c;其他的线程不能对其进行访问&#xff0c;直到该线程访问完毕。简单来讲就是在同一时刻&#xff0c;对同一个数据操作的线程只有一个。而线程不安全&#xff0c;则是在同一时刻可以有多个线程对该数据进行访问&#xff0c;从而得…...

杰发科技(合肥)2021笔试题

笔试时间:2020.10.17 ,10:30-12:00。 岗位:Linux 驱动工程师。 题型:选择题8道,填空题10道,编程题4道。 杰发科技主要做汽车电子,由北京四维图新控股,对汽车电子感兴趣的有机会可以应聘试试。 选择题 1、128,4 #include<stdio.h> unsigned int getstrsiz…...

Java堆排序

目录 PriorityQueue自己实现 PriorityQueue public class PriorityQueueMain {public static void main(String[] args) {int[] temp {40, 2, 33, 26, 35, 8, 8, 26, 29, 2};PriorityQueue<Integer> priorityQueue new PriorityQueue<>();for (int i 0; i <…...

GitHub的基本使用教程

GitHub是一个基于web的版本控制和协作平台。它允许开发人员将他们的代码存储库存储在云中&#xff0c;并与其他人一起进行工作。GitHub还提供了各种工具和功能来帮助开发人员管理和组织他们的代码项目&#xff0c;包括拉出请求、问题跟踪、代码评论等等。此外&#xff0c;它托管…...

objectMapper.configure 方法的作用和使用

objectMapper.configure 方法是 Jackson 提供的一个用于配置 ObjectMapper 对象的方法。ObjectMapper 是 Jackson 库的核心类&#xff0c;用于将 Java 对象与 JSON 数据相互转换。 configure 方法的作用是设置 ObjectMapper 的配置选项&#xff0c;例如设置日期格式、设置序列…...

面试热题(x的平方根)

给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 注意&#xff1a;不允许使用任何内置指数函数和算符&#xff0c;例如 pow(x, 0.5) 或者 x ** 0.5 。 这道题虽然是简单题…...

食品溯源合约 -- 智能合约实例

前提 Roles: 实现对用户地址的角色权限管控,添加、删除角色。 Producer: 生产商角色管控。 ... FoodInfoItem: 食品信息管控。生产商、中间商、超市添加食品信息。 Trace:食品溯源合约,主要负责对以上几个合约的统筹协作。 Roles // SPDX-License-Identifier: MIT pragm…...

SAP系统中二代增强提供了4中增强函数的查找方法

1 Introduction The second enhancement is used widely by sap .We can set break-point in the function . The function is in the SMOD FG. 2 Detail SAP系统中二代增强提供了4中增强函数的查找方法&#xff1a; MODX_ALL_ACTIVE_MENUENTRIES (菜单增强) MODX_FUNCTION…...

RabbitMQ-SpringBoot2

1.依赖引用 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2.配置文件 spring: rabbitmq: host: 192.168.2.17 port: 5672 usernam…...

MyBatis核心 - SqlSession如何通过Mapper接口生成Mapper对象

书接上文 MyBatis – 执行流程 我们通过SqlSession获取到了UserMapper对象&#xff0c;代码如下&#xff1a; // 获取SqlSession对象 SqlSession sqlSession sqlSessionFactory.openSession();// 执行查询操作 try {// 获取映射器接口UserMapper userMapper sqlSession.get…...

【Git】标签管理与Git Flow模型

目录 一、操作标签 二、推送标签 三、删除标签 四、Git Flow模型分支设计 一、操作标签 git tag # 查看有哪些标签 git tag [name] # 给最近一次commit打标签 git tag [name] [commitID] #给指定的commit打标签 git tag -a [name] -m desc # 打标签并添加描述 二、推送标…...

日志分析和流量分析

目录 [陇剑杯 2021]日志分析&#xff08;问1&#xff09; [陇剑杯 2021]日志分析&#xff08;问2&#xff09; [陇剑杯 2021]日志分析&#xff08;问3&#xff09; [陇剑杯 2021]简单日志分析&#xff08;问1&#xff09; [陇剑杯 2021]简单日志分析&#xff08;问3&#…...

typescript基础之关键字type

TypeScript的type是一个关键字&#xff0c;用来定义一个类型别名https://www.typescripttutorial.net/typescript-tutorial/typescript-types/。类型别名可以给一个已有的类型起一个新的名字&#xff0c;或者组合多个类型成为一个新的类型。例如&#xff1a; // 给string类型起…...

无人机航测技术有何特点?主要应用在哪些方面?

无人机航测是航空摄影测量的一种&#xff0c;主要面向低空遥感领域&#xff0c;具有成本低、快速高效、适用范围广等特点。目前&#xff0c;无人机航测主要应用于地形测绘、城市数字化建设、工程建设等方面。 无人机航测技术的特点 1、作业成本低 传统的人工测量技术主要利用…...

Linux日志高效搜索:从基础grep到journalctl实战技巧

1. Linux日志搜索&#xff1a;运维工程师的必备技能 每次服务器出现异常&#xff0c;第一反应是什么&#xff1f;没错&#xff0c;就是查日志。作为在Linux系统摸爬滚打多年的老运维&#xff0c;我见过太多新手面对海量日志时的手足无措。其实日志排查就像破案&#xff0c;关键…...

英飞凌TC3XX时钟系统实战:从PLL配置到CCU分频的避坑指南

英飞凌TC3XX时钟系统实战&#xff1a;从PLL配置到CCU分频的避坑指南 在嵌入式系统开发中&#xff0c;时钟系统如同人体的神经系统&#xff0c;为整个芯片提供精准的时序控制和同步信号。作为英飞凌AURIX™系列中的旗舰产品&#xff0c;TC3XX微控制器凭借其高度可配置的时钟架构…...

项目介绍 MATLAB实现基于概率路图法(PRM)进行无人机三维路径规划的详细项目实例(含模型描述及部分示例代码) 专栏近期有大量优惠 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持

MATLAB实现基于概率路图法&#xff08;PRM&#xff09;进行无人机三维路径规划的详细项目实例 更多详细内容可直接联系博主本人 或者访问对应标题的完整博客或者文档下载页面&#xff08;含完整的程序&#xff0c;GUI设计和代码详解&#xff09; 随着无人机技术的快速发展&…...

Pixel Epic部署指南:GPU显存监控+自动降级策略+OOM防护机制

Pixel Epic部署指南&#xff1a;GPU显存监控自动降级策略OOM防护机制 1. 像素史诗终端概述 Pixel Epic&#xff08;像素史诗&#xff09;是一款基于AgentCPM-Report大模型构建的研究报告辅助终端&#xff0c;将严肃的科研过程转化为富有游戏感的交互体验。与传统AI工具不同&a…...

毫米波行波管核心:折叠波导慢波结构原理、优势、对比与设计实战

在毫米波行波管&#xff08;TWT&#xff09;领域&#xff0c;折叠波导慢波结构&#xff08;FW-SWS&#xff09; 是无可争议的 “王者”—— 它凭借全金属结构、高功率容量、宽频带和成熟的加工工艺&#xff0c;在 Ka 波段及以上的功率器件中占据绝对主导地位&#xff0c;是卫星…...

抖音视频批量下载终极指南:5分钟掌握高效下载技巧

抖音视频批量下载终极指南&#xff1a;5分钟掌握高效下载技巧 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. …...

从SEED-Labs实验到实战:手把手教你编写无零字节的x86 Shellcode(附完整代码)

从SEED-Labs实验到实战&#xff1a;手把手教你编写无零字节的x86 Shellcode&#xff08;附完整代码&#xff09; 当你第一次看到"Shellcode"这个词时&#xff0c;可能会联想到某种神秘的编程黑魔法。实际上&#xff0c;它是安全研究中最具实用价值的技能之一——一段…...

5步搞定Jimeng LoRA测试台:Streamlit界面,LoRA版本智能排序

5步搞定Jimeng LoRA测试台&#xff1a;Streamlit界面&#xff0c;LoRA版本智能排序 1. 项目概述&#xff1a;轻量级LoRA测试系统 Jimeng LoRA测试台是一款专为模型开发者设计的轻量化文本生成图像系统。它基于Z-Image-Turbo文生图底座&#xff0c;实现了动态多版本LoRA热切换…...

WeMod Patcher终极实战指南:3步解锁Pro功能的完整方案

WeMod Patcher终极实战指南&#xff1a;3步解锁Pro功能的完整方案 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer WeMod Patcher是一款开源的游戏辅助工…...

快速原型:用快马一键生成win11右键菜单传统样式恢复工具

快速原型&#xff1a;用快马一键生成win11右键菜单传统样式恢复工具 最近升级到Windows 11后&#xff0c;最让我不习惯的就是那个右键菜单了。新版的设计把所有选项都折叠起来&#xff0c;每次想找个功能还得点"显示更多选项"&#xff0c;效率大打折扣。作为一个习惯…...