JUC并发编程之等待唤醒机制

目录

1. 线程等待唤醒机制

1.1 使用Object的wait()和notify()方法

1.2 使用Condition接口

1.3 使用LockSupport类


1. 线程等待唤醒机制

在JUC(Java Util Concurrent)并发编程中,线程等待唤醒机制是实现线程之间协作和同步的重要手段。这种机制允许一个线程挂起等待某个条件满足后被唤醒,以及另一个线程在满足某个条件后唤醒等待的线程。在Java中,有多种实现线程等待唤醒机制的方式,包括使用Objectwait()notify()方法、Condition接口以及LockSupport类。

1.1 使用Objectwait()notify()方法

Object类是Java中所有类的父类,在多线程编程中,我们可以利用Objectwait()notify()方法实现线程等待唤醒机制。这种方式需要在同步代码块中进行操作,因为wait()notify()方法必须在同步块中调用。

public class WaitNotifyExample {public static void main(String[] args) {final Object lock = new Object();Thread waitingThread = new Thread(() -> {synchronized (lock) {System.out.println("Waiting thread: Started waiting...");try {lock.wait(); // 线程等待,释放锁} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Waiting thread: Resumed!");}});Thread notifyingThread = new Thread(() -> {synchronized (lock) {System.out.println("Notifying thread: Started notifying...");lock.notify(); // 唤醒等待线程System.out.println("Notifying thread: Finished notifying");}});waitingThread.start();try {Thread.sleep(1000); // 确保等待线程先执行} catch (InterruptedException e) {e.printStackTrace();}notifyingThread.start();}
}

在上面的示例中,我们创建了两个线程:waitingThreadnotifyingThreadwaitingThread首先获取锁并调用lock.wait(),进入等待状态,并释放了锁。接着,notifyingThread获取锁,调用lock.notify()唤醒了等待线程。注意,wait()notify()方法都必须在synchronized块内部使用,否则会抛出IllegalMonitorStateException

1.2 使用Condition接口

Condition接口是Java并发包(java.util.concurrent.locks)中的一部分,它提供了类似于Objectwait()notify()方法的功能,但更加灵活。可以在一个Lock对象上通过Condition来实现线程的等待和唤醒。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ConditionExample {public static void main(String[] args) {final Lock lock = new ReentrantLock();final Condition condition = lock.newCondition();Thread waitingThread = new Thread(() -> {lock.lock();try {System.out.println("Waiting thread: Started waiting...");condition.await(); // 线程等待System.out.println("Waiting thread: Resumed!");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}});Thread notifyingThread = new Thread(() -> {lock.lock();try {System.out.println("Notifying thread: Started notifying...");condition.signal(); // 唤醒等待线程System.out.println("Notifying thread: Finished notifying");} finally {lock.unlock();}});waitingThread.start();try {Thread.sleep(1000); // 确保等待线程先执行} catch (InterruptedException e) {e.printStackTrace();}notifyingThread.start();}
}

在上述示例中,我们使用了ReentrantLock作为锁,通过调用lock.newCondition()创建了一个与该锁关联的Condition实例。然后,等待线程在等待前调用condition.await()进行等待,而唤醒线程通过condition.signal()来唤醒等待的线程。

1.3 使用LockSupport

LockSupport类是Java并发包(java.util.concurrent.locks)中的工具类,它提供了一种基于线程的阻塞和唤醒机制,不需要依赖于特定的对象实例。

LockSupport的实现依赖于每个线程持有的一个许可(permit)。线程调用park()方法时,如果它持有许可,则立即返回;否则,将会阻塞(挂起)。线程调用unpark(Thread thread)方法时,如果线程处于挂起状态且持有许可,则会使其恢复运行。如果线程尚未调用park()方法或之前已经调用过unpark()方法,并且还持有许可,则后续的park()调用将不会阻塞。而Object类实现线程等待唤醒机制中先notify再wait就会一直处于阻塞状态,Condition接口同理。

LockSupport使用了类似信号量的机制,只有一个许可可供线程使用。如果一个线程调用了unpark(Thread thread)方法,而目标线程还没有调用park()方法,那么目标线程在之后调用park()方法时将立即返回,而不会阻塞。

在内部实现上,LockSupport使用了一些底层的Java本地接口(JNI)来实现线程的挂起和恢复。它通过修改线程的内部状态来达到挂起和恢复线程的目的。

import java.util.concurrent.locks.LockSupport;public class LockSupportExample {public static void main(String[] args) {Thread waitingThread = new Thread(() -> {System.out.println("Waiting thread: Started waiting...");LockSupport.park(); // 线程挂起System.out.println("Waiting thread: Resumed!");});Thread notifyingThread = new Thread(() -> {System.out.println("Notifying thread: Started notifying...");LockSupport.unpark(waitingThread); // 唤醒线程System.out.println("Notifying thread: Finished notifying");});waitingThread.start();try {Thread.sleep(1000); // 确保等待线程先执行} catch (InterruptedException e) {e.printStackTrace();}notifyingThread.start();}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC(Artificial Intelligence and Graph Computing)职业发展路径和前景如何?

目录 一、AIGC 基本概念二、AIGC 市场规模三、AIGC 未来发展前景四、AIGC 职业发展路径五、AIGC 技能要求六、AIGC 相关公司 AIGC(Artificial Intelligence and Graph Computing)是人工智能和图计算的结合,它是一种用于处理大规模复杂数据的计…

暑假刷题第16天--7/28

143. 最大异或对 - AcWing题库&#xff08;字典树&#xff09; #include<iostream> using namespace std; const int N100005; int a[N]; int nex[10000007][2],cnt; void insert(int x){int p0;for(int i30;i>0;i--){int ux>>i&1;if(!nex[p][u])nex[p][u]…

java排序算法之插入排序

文章目录 &#x1f4cb;插入排序概念&#x1f4d6;实现步骤&#x1f516;代码示例 &#x1f4c8;总结 &#x1f4cb;插入排序概念 插入排序&#xff08;Insertion Sort&#xff09;是一种简单直观的排序算法。它将数组划分为已排序和未排序两个部分&#xff0c;每次从未排序部分…

Linux 多线程并发Socket服务端的实现( 11 ) -【Linux通信架构系列 】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everythi…

25.9 matlab里面的10中优化方法介绍—— 惩罚函数法求约束最优化问题(matlab程序)

1.简述 一、算法原理 1、问题引入 之前我们了解过的算法大部分都是无约束优化问题&#xff0c;其算法有&#xff1a;黄金分割法&#xff0c;牛顿法&#xff0c;拟牛顿法&#xff0c;共轭梯度法&#xff0c;单纯性法等。但在实际工程问题中&#xff0c;大多数优化问题都属于有约…

SpringBoot读取配置文件顺序

文章目录 一、前言二、SpringBoot配置文件目录读取顺序源码解析 三、SpringBoot配置文件类型读取顺序源码解析 一、前言 本文通过源码分析 SpringBoot 加载配置文件目录的顺序&#xff0c;以及 properties、xml、yml、yaml文件的读取顺序 二、SpringBoot配置文件目录读取顺序…

【MySQL】库的操作

废话不多说&#xff0c;直接上操作&#xff1a; 目录 一、查看数据库 二、创建数据库 2.1 数据库的字符集及校验规则 2.1.1 查看系统默认字符集 2.1.2 查看系统默认校验规则 2.1.3 查看数据库支持的字符集 2.1.4 查看数据库支持的校验规则 2.2 创建数据库时设置字符集和…

【二叉树进阶】搜索二叉树(递归+非递归两种版本详解)

文章目录 前言1. 二叉搜索树的概念2. 二叉搜索树的结构2.1 结点结构2.2 树结构 3. 插入操作&#xff08;非递归&#xff09;3.1 思路分析3.2 代码实现3.3 中序遍历&#xff08;测试用&#xff09; 4. 查找操作&#xff08;非递归&#xff09;4.1 思路分析4.2 代码实现 5. 删除操…

【设计模式】观察者设计模式解析

目录 一、观察者模式定义 二、观察者模式角色 三、观察者模式类图 四、观察者模式实例 五、观察者模式优缺点 5.1、优点 5.2、缺点 六、观察者模式应用 6.1、Spring 中观察者模式的四个角色 6.2、coding~~~~~~ 一、观察者模式定义 观察者模式(Observer Pattern)&#…

【如何训练一个中英翻译模型】LSTM机器翻译模型训练与保存(二)

系列文章 【如何训练一个中英翻译模型】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中英翻译模型】LSTM机器翻译模型部署&#xff08;三&#xff09; 【如何训…

【框架篇】Spring Boot 日志

Spring Boot 日志 一&#xff0c;日志用途 尽管一个项目在没有日志记录的情况下可能能够正常运行&#xff0c;但是日志记录对于我们来说却是至关重要的&#xff0c;它存在以下功能&#xff1a; 1&#xff0c;故障排查和调试&#xff1a;当项目出现异常或者故障时&#xff0c;…

idea连接远程服务器上传war包文件

idea连接远程服务器&上传war包 文章目录 idea连接远程服务器&上传war包1. 连接服务器2.上传war包 1. 连接服务器 选择Tools -> Start SSH Session 添加配置 连接成功 2.上传war包 Tools -> Deployment -> Browse Remote Host 点击右侧标签&#xff0c;点击&…

gin框架内容(三)--中间件

gin框架内容&#xff08;三&#xff09;--中间件 Gin框架允许开发者在处理请求的过程中&#xff0c;加入用户自己的函数。这个函数就叫中间件&#xff0c;中间件适合处理一些公共的业务逻辑&#xff0c;比如登录认证、权限校验、数据分页、记录日志、耗时统计等 即比如&#x…

MySQL - 4、数据聚合和函数:

0、创建示例表并插入数据&#xff1a; CREATE TABLE orders (order_id INT PRIMARY KEY AUTO_INCREMENT,customer_name VARCHAR(50) NOT NULL,order_date DATE,total_amount DECIMAL(10, 2) );INSERT INTO orders (customer_name, order_date, total_amount) VALUES(lfsun-1, …

【java设计模式】创建型模式介绍(工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式)

文章目录 简介一、工厂模式介绍案例 二、抽象工厂模式介绍案例 三、单例模式介绍案例 四、建造者模式介绍案例 五、原型模式介绍案例 简介 本文介绍Java设计模式中创建型模式的五种 一、工厂模式 工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式…

使用分布式HTTP代理爬虫实现数据抓取与分析的案例研究

在当今信息爆炸的时代&#xff0c;数据已经成为企业决策和发展的核心资源。然而&#xff0c;要获取大规模的数据并进行有效的分析是一项艰巨的任务。为了解决这一难题&#xff0c;我们进行了一项案例研究&#xff0c;通过使用分布式HTTP代理爬虫&#xff0c;实现数据抓取与分析…

华为eNSP:isis的配置

一、拓扑图 二、路由器的配置 配置接口IP AR1&#xff1a; <Huawei>system-view [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [Huawei-GigabitEthernet0/0/0]qu AR2: <Huawei>system-view [Huawei]int g0/0/0 [Huawei-GigabitEthe…

【用IDEA基于Scala2.12.18开发Spark 3.4.1 项目】

目录 使用IDEA创建Spark项目设置sbt依赖创建Spark 项目结构新建Scala代码 使用IDEA创建Spark项目 打开IDEA后选址新建项目 选址sbt选项 配置JDK debug 解决方案 相关的依赖下载出问题多的话&#xff0c;可以关闭idea&#xff0c;重启再等等即可。 设置sbt依赖 将sbt…

Django学习笔记-模板(Template)基础

使用模块可以很方便的执行一些数据操作&#xff0c;然后根据传入的数据直接在模板html文件中进行处理。 1.Django中的模板配置 Django的模板引擎在sttings.py文件中&#xff1a; TEMPLATES [{# 模板引擎&#xff0c;默认为django模板BACKEND: django.template.backends.dja…

QTday4(鼠标事件和键盘事件/QT实现连接TCP协议)

笔记 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QTcpServer>//服务器类 #include <QTcpSocket>//客户端类 #include <QMessageBox> #include <QList>//链表容器QT_BEGIN_NAMESPACE namespace Ui …