聊聊并发编程——Condition

目录

一.synchronized + wait/notify/notifyAll = 线程通信

二.Lock + Condition 实现线程通信

三.Condition实现通信分析

四.JUC工具类的示例


一.synchronized + wait/notify/notifyAll = 线程通信

关于线程间的通信,简单举例下:

1.创建ThreadA传入共享资源对象获取锁,执行业务后wait释放锁。

public class ThreadA extends Thread{private Object lock;public  ThreadA(Object lock){this.lock = lock;}@Overridepublic void run() {synchronized (lock) {System.out.println("ThreadA start");try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("ThreadA end");}}
}

2.创建ThreadB获取共享资源对象的锁,执行notify执行业务后会唤醒等待队列中的线程。

public class ThreadB extends Thread{private Object lock;public ThreadB(Object lock){this.lock = lock;}@Overridepublic void run() {synchronized (lock) {System.out.println("ThreadB start");lock.notify();System.out.println("ThreadB end");}}
}

3.创建A线程B线程验证,执行结果:

public class WaitNotify {public static void main(String[] args) {Object lock = new Object();ThreadA threadA = new ThreadA(lock);threadA.start();
​ThreadB threadB = new ThreadB(lock);threadB.start();}
}

执行结果:

线程间wait、notify通信的流程分析如下所示:

二.Lock + Condition 实现线程通信

Condition定义了等待/通知两种类型的方法,当前线程调用这些方法时,需要提前获取到 Condition对象关联的锁。Condition对象是由Lock对象(调用Lock对象的newCondition()方法)创 建出来的,换句话说,Condition是依赖Lock对象的。

public class ConditionWait implements Runnable{private Lock lock;
​private Condition condition;
​public ConditionWait(Lock lock, Condition condition) {this.lock = lock;this.condition = condition;}
​@Overridepublic void run() {lock.lock();try {System.out.println("start - ConditionWait...");condition.await();System.out.println("end - ConditionWait");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}
}
public class ConditionNotify implements Runnable{private Lock lock;private Condition condition;
​public ConditionNotify(Lock lock, Condition condition) {this.lock = lock;this.condition = condition;}
​@Overridepublic void run() {lock.lock();try {System.out.println("start - ConditionNotify...");condition.signal();System.out.println("end - ConditionNotify...");} finally {lock.unlock();}}
}
public class ConditionCommunication {public static void main(String[] args) {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();new Thread(new ConditionWait(lock, condition), "await").start();  // 1new Thread(new ConditionNotify(lock, condition), "signal").start(); // 2}
}

输出结果:

如果把1和2顺序交换,ConditionWait的唤醒就会一直阻塞。输出结果:

三.Condition实现通信分析

线程 awaitThread 先通过 lock.lock()方法获取锁成功 后调用了 condition.await 方法进入等待队列,而另一个 线程 signalThread 通过 lock.lock()方法获取锁成功后调用 了 condition.signal 或者 signalAll 方法,使得线程 awaitThread 能够有机会移入到同步队列中,当其他线程释放 lock 后使得线程 awaitThread 能够有机会获取 lock,从而使得线程 awaitThread 能够从 await 方法中退出执行后续操作。如果 awaitThread 获取 lock 失败会直 接进入到同步队列。

阻塞:await()方法中,在线程释放锁资源之后,如果节点 不在 AQS 等待队列,则阻塞当前线程,如果在等待队 列,则自旋等待尝试获取锁 释放:signal()后,节点会从 condition 队列移动到 AQS 等待队列,则进入正常锁的获取流程。

四.JUC工具类的示例
  1. CountDownLatch(倒计数门栓)

    • 用途:CountDownLatch用于等待一个或多个线程完成某个操作。它初始化一个计数器,然后一个或多个线程等待这个计数器变为零,一旦变为零,等待的线程被唤醒。

    • 示例:常见于主线程等待多个工作线程全部完成后再执行的场景。

    CountDownLatch latch = new CountDownLatch(3); // 初始化计数器为3
    // 启动三个工作线程
    new Thread(() -> {// 执行任务latch.countDown(); // 减少计数器
    }).start();
    ​
    // 其他两个线程类似
    ​
    latch.await(); // 主线程等待计数器变为0
  2. CyclicBarrier(循环屏障)

    • 用途:CyclicBarrier用于多个线程互相等待,直到所有线程都到达某个屏障点,然后同时执行下一步操作。它可重复使用,因此在每个线程完成后,可以重复使用CyclicBarrier等待下一轮。

    • 示例:常见于多个线程同时进行某个任务,然后在某个点同步结果。

    CyclicBarrier barrier = new CyclicBarrier(3); // 初始化屏障为3
    // 启动三个工作线程
    new Thread(() -> {// 执行任务barrier.await(); // 等待其他线程到达屏障
    }).start();
    ​
    // 其他两个线程类似
  3. Semaphore(信号量)

    • 用途:Semaphore用于控制对某一资源的访问线程数。它维护一个计数器,每次线程访问资源时,计数器减一,当计数器为零时,其他线程需要等待。

    • 示例:常见于限制同时访问某一资源的线程数量的场景。

    Semaphore semaphore = new Semaphore(3); // 初始化信号量为3,允许3个线程同时访问
    // 启动多个线程尝试访问资源
    new Thread(() -> {try {semaphore.acquire(); // 获取资源// 执行任务} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release(); // 释放资源}
    }).start();
    ​
    // 其他线程类似
  4. Exchanger(交换器)

    • 用途:Exchanger用于两个线程之间交换数据,每个线程将数据放入Exchanger后等待,当两个线程都到达时,它们可以交换数据然后继续执行。

    • 示例:常见于两个线程之间协同工作,互相交换数据的场景。

    Exchanger<String> exchanger = new Exchanger<>();
    // 启动两个线程,交换数据
    new Thread(() -> {try {String data = "Thread A data";exchanger.exchange(data); // 等待交换数据// 处理对方线程的数据} catch (InterruptedException e) {e.printStackTrace();}
    }).start();
    ​
    // 另一个线程类似

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

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

相关文章

(一)NIO 基础

&#xff08;一&#xff09;NIO 基础 non-blocking io&#xff1a;非阻塞 IO 1、三大组件 1.1、Channel & Buffer Java NIO系统的核心在于&#xff1a;通道&#xff08;Channel&#xff09;和缓冲&#xff08;Buffer&#xff09;。通道表示打开到 IO 设备&#xff08;例…

【golang】调度系列之sysmon

调度系列 调度系列之goroutine 调度系列之m 调度系列之p 掉地系列之整体介绍 在golang的调度体系中&#xff0c;除了GMP本身&#xff0c;还有另外一个比较重要的角色sysmon。实际上&#xff0c;除了GMP和sysmon&#xff0c;runtime中还有一个全局的调度器对象。但该对象只是维护…

浅谈AVL树

文章目录 1.介绍1.1定义1.2来源1.3概念1.特性2.平衡因子[ Balance Factor-- _bf ] 2.BST>AVL1.示例分析2.情况分类3.代码剖析3.1左左型-右单旋3.2右右型-左单旋3.3左右型-左右旋3.4右左型:右左旋3.5总图 3.完整代码3.1AVLTree.h3.2Test.cpp 1.介绍 1.1定义 AVL树 – 平衡二…

RabbitMQ(15672) 消息中间件 NOTE

目录 1、初识 RabbitMQ 消息队列 1.1 MQ 四大核心概念 1.2 消息的发送&#xff08;无交换机态&#xff09; 1.3 关于消息自动重新入队 1.3.1 消息的常见应答方法&#xff08;R&#xff09; 1.4 关于 RabbitMQ 的持久化、不公平分发以及预取值 2、RabbitMQ 消息的发布确认…

centos7用docker安装WireGuard教程

PS:本文章用于帮助组建自己内网或者公司组网操作,该教程不涉及翻墙操作. 1、 检查centos内核版本 uname -r2、升级内核 下载脚本上传到服务器运行脚本进行升级内核 链接&#xff1a;https://pan.baidu.com/s/1vYmqVy2St3nFnJWGPIwdOw 提取码&#xff1a;owac 3、安装WireG…

云原生Kubernetes:K8S安全机制

目录 一、理论 1.K8S安全机制 2.Authentication认证 3.Authorization授权 4.Admission Control准入控制 5.User访问案例 6.ServiceAccount访问案例 二、实验 1.Admission Control准入控制 2.User访问案例 3.ServiceAccount访问案例 三、问题 1.生成资源报错 2.镜…

7.2 怎样定义函数

7.2.1 为什么要定义函数 主要内容&#xff1a; 为什么要定义函数 C语言要求所有在程序中用到的函数必须“先定义&#xff0c;后使用”。这是因为在调用一个函数之前&#xff0c;编译系统需要知道这个函数的名字、返回值类型、功能以及参数的个数与类型。如果没有事先定义&…

多叉树+图实现简单业务流程

文章目录 场景整体架构流程业务界面技术细节小结 场景 这次遇到一个需求,大致就是任务组织成方案,方案组织成预案,预案可裁剪调整.预案关联事件等级配置,告警触发预案产生事件.然后任务执行是有先后的,也就是有流程概念. 整体架构流程 方案管理、预案管理构成任务流程的基础条…

nginx 多层代理 + k8s ingress 后端服务获取客户真实ip 配置

1.nginx http 七层代理 修改命令空间&#xff1a; namespace: nginx-ingress : configmap&#xff1a;nginx-configuration kubectl get cm nginx-configuration -n ingress-nginx -o yaml添加如上配置 compute-full-forwarded-for: “true” forwarded-for-header: X-Forwa…

.balckhoues-V-XXXXXXX勒索病毒数据怎么处理|数据解密恢复

引言&#xff1a; 随着网络犯罪的不断演进&#xff0c;勒索病毒已成为当前数字时代的威胁之一&#xff0c;其中包括.balckhoues-V-XXXXXXX勒索病毒。本文将深入介绍.balckhoues-V-XXXXXXX勒索病毒的特点、数据恢复方法以及预防措施&#xff0c;以帮助您更好地理解和应对这一威…

NPDP产品经理认证怎么报名?考试难度大吗?

PMDA&#xff08;Product Development and Management Association&#xff09;是美国产品开发与管理协会&#xff0c;在中国由中国人才交流基金会培训中心举办NPDP&#xff08;New Product Development Professional&#xff09;考试&#xff0c;该考试是产品经理国际资格认证…

Spring实例化源码解析之ComponentScanAnnotationParser(四)

上一章我们分析了ConfigurationClassParser&#xff0c;配置类的解析源码分析。在ComponentScans和ComponentScan注解修饰的候选配置类的解析过程中&#xff0c;我们需要深入的了解一下ComponentScanAnnotationParser的parse执行流程&#xff0c;SpringBoot启动类为什么这么写&…

WinPcap4.1.3安装失败解决方法,A newer version of winpcap...

WinPcap4.1.3安装失败解决方法&#xff0c;A newer version of winpcap… 如图所示&#xff0c;提示本地安装有更高版本的WinPcap时&#xff0c;按如下操作即可解决。 找到相应文件&#xff0c;扩展名修改成如下&#xff1a; C:\Windows\SysWOW64 的wpcap.dll改成 wpcap.dll.…

【Verilog 教程】6.5 Verilog避免Latch

关键词&#xff1a;触发器&#xff0c;锁存器 Latch 的含义 锁存器&#xff08;Latch&#xff09;&#xff0c;是电平触发的存储单元&#xff0c;数据存储的动作取决于输入时钟&#xff08;或者使能&#xff09;信号的电平值。仅当锁存器处于使能状态时&#xff0c;输出才会随着…

使用 Velocity 模板引擎的 Spring Boot 应用

使用 Velocity 模板引擎的 Spring Boot 应用 模板引擎是构建动态内容的重要工具&#xff0c;特别适用于生成HTML、邮件内容、报告和其他文本文档。Velocity是一个强大的模板引擎&#xff0c;它具有简单易用的语法和灵活性。本文将介绍如何在Spring Boot应用中使用Velocity模板…

C语言入门Day_27 开发环境

前言&#xff1a; 在线编译环境涉及到联网&#xff0c;如果在没有网的情况下&#xff0c;我们就不能写代码了&#xff0c;这一章节&#xff0c;我们将会给大家介绍一下如何搭建一个本地的C语言编译环境。 如果想要设置 C 语言环境&#xff0c;需要确保电脑上有以下两款可用的…

二十二,加上各种贴图

使用pbr的各种贴图&#xff0c;albedo,金属度&#xff0c;ao,法线&#xff0c;粗糙度&#xff0c;可以更好的控制各个片元 1&#xff0c;先加上纹理坐标 texCoords->push_back(osg::Vec2(xSegment, ySegment)); geom->setVertexAttribArray(3, texCoords, osg::Array::BI…

凹凸贴图如何提高物体的真实感

什么是凹凸贴图 凹凸贴图&#xff08;Bump Mapping&#xff09;是一种计算机图形学中的技术&#xff0c;用于在表面上模拟微小的凹凸形状&#xff0c;从而增加了物体的细节和真实感。它可以在不改变物体几何形状的情况下&#xff0c;通过修改光照的反应&#xff0c;使表面看起来…

Java编程技巧:文件上传、下载、预览

目录 1、上传文件1.1、代码1.2、postman测试截图 2、下载resources目录中的模板文件2.1、项目结构2.2、代码2.3、使用场景 3、预览文件3.1、项目结构3.2、代码3.3、使用场景 1、上传文件 1.1、代码 PostMapping("/uploadFile") public String uploadFile(Multipart…

idea Springboot 高校科研资源共享系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 高校科研资源共享系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c; 系统具有完整的源代码和数据…