java并发控制(猴子摘桃例子)

【问题】

有n个桃子, 猴子A每次固定摘2个,猴子B每次固定摘3个,这2只猴子不断摘桃子直到剩余桃子数量不足以摘(必须满足摘桃个数);


【1】 使用AtomicInteger(推荐)

1)利用 原子类的CAS原子函数(乐观锁)实现并发控制访问;

2)推荐; 乐观锁实现,代码简单,性能高; 

public class AtomicIntegerTest {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(2);Object lock = new Object();AtomicInteger cap = new AtomicInteger(103);executorService.execute(new Task(cap, 2));executorService.execute(new Task(cap, 3));executorService.shutdown();}private static class Task implements Runnable {private AtomicInteger cap;private int consumeSize;private int takeCount = 0;Task(AtomicInteger cap, int consumeSize) {this.cap = cap;this.consumeSize = consumeSize;}@Overridepublic void run() {while (take()) ;PrintUtils.print(Thread.currentThread().getName() + "#" + this);}boolean take() {if (cap.addAndGet(-consumeSize) >= 0) {takeCount++;return true;}return false;}@Overridepublic String toString() {return "Task{" +"consumeSize=" + consumeSize +", takeCount=" + takeCount +'}';}}
}

【2】使用synchronized同步代码块

监视器锁内存结构:

1)用户线程访问Synchronized同步代码块获取锁流程

2)代码示例

public class SynchronizedTest {private static volatile Integer CAPACITY = 14;public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(2);Object lock = new Object();executorService.execute(new Task( 2, lock));executorService.execute(new Task( 3, lock));executorService.shutdown();}static class Task implements Runnable {private int consumeSize;private Object lock;private int takeCount = 0;Task(int consumeSize, Object lock) {this.consumeSize = consumeSize;this.lock = lock;}@Overridepublic void run() {while(take());PrintUtils.print(Thread.currentThread().getName() + "#" + this);}boolean take() {synchronized (lock) {if (CAPACITY >= consumeSize) {CAPACITY -= consumeSize;takeCount++;return true;}return false;}}@Overridepublic String toString() {return "Task{" +"consumeSize=" + consumeSize +", takeCount=" + takeCount +'}';}}
}
2024-06-09 10:42:56.989 pool-1-thread-1#Task{consumeSize=2, takeCount=4}
2024-06-09 10:42:56.989 pool-1-thread-2#Task{consumeSize=3, takeCount=2}

【3】使用可重入锁ReentrantLock

public class ReentrantLockTest {private static volatile Integer CAPACITY = 103;public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(2);ReentrantLock reentrantLock = new ReentrantLock();executorService.execute(new Task(2, reentrantLock));executorService.execute(new Task(3, reentrantLock));executorService.shutdown();}static class Task implements Runnable {private int consumeSize;private ReentrantLock reentrantLock;private int takeCount = 0;Task(int consumeSize, ReentrantLock reentrantLock) {this.consumeSize = consumeSize;this.reentrantLock = reentrantLock;}@Overridepublic void run() {while (take()) ;PrintUtils.print(Thread.currentThread().getName() + "#" + this);}boolean take() {reentrantLock.lock(); // 加锁try {if (CAPACITY >= consumeSize) {CAPACITY -= consumeSize;takeCount++;return true;}return false;} finally {reentrantLock.unlock(); // 解锁}}@Overridepublic String toString() {return "Task{" +"consumeSize=" + consumeSize +", takeCount=" + takeCount +'}';}}
}


【4】 使用信号量Semaphore实现

semaphore.acquire()#信号量个数减1 和 release()#信号量个数加1 ;如信号量个数等于0,则 acquire() 阻塞;

public class SemaphoreTest {private static volatile Integer CAPACITY = 103;public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(2);Semaphore semaphore = new Semaphore(1);// 信号量数量初始为1 executorService.execute(new Task(2, semaphore));executorService.execute(new Task(3, semaphore));executorService.shutdown();}static class Task implements Runnable {private int consumeSize;private Semaphore semaphore;private int takeCount = 0;Task(int consumeSize, Semaphore semaphore) {this.consumeSize = consumeSize;this.semaphore = semaphore;}@Overridepublic void run() {while (take()) ;PrintUtils.print(Thread.currentThread().getName() + "#" + this);}boolean take() {// 获取信号量(信号数量减1)try {semaphore.acquire();if (CAPACITY >= consumeSize) {CAPACITY -= consumeSize;takeCount++;return true;}return false;} catch (Exception e) {throw new RuntimeException(e);} finally {semaphore.release();}}@Overridepublic String toString() {return "Task{" +"consumeSize=" + consumeSize +", takeCount=" + takeCount +'}';}}
}
2024-06-09 14:20:18.509 pool-1-thread-2#Task{consumeSize=3, takeCount=5}
2024-06-09 14:20:18.509 pool-1-thread-1#Task{consumeSize=2, takeCount=44}

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

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

相关文章

iOS--block再学习

block再学习 什么是blockblock是带有自动变量的匿名函数block语法 block的实现block的实质截获自动变量__blcok说明符Block存储域__block变量存储域使用__block变量用结构体成员变量__forwarding的原因 截获对象 什么是block Block时c语言的扩充功能,它允许开发者定…

pytorch之猫狗识别项目

1. 导入资源包 资源包: import torchvision:PyTorch 提供的视觉库,包含了常用的计算机视觉模型架构、数据集以及图像转换工具。 from torchvision import datasets, models:导入 torchvision 中的 datasets 和 models 模块&#…

spring boot +Scheduled 动态定时任务配置

通常情况下我们设定的定时任务都是固定的,有时候需要我们动态的配置定时任务,下面看代码 import com.mybatisflex.core.query.QueryWrapper; import com.yzsec.dsg.web.modules.exportpwd.entity.ExportPwd; import com.yzsec.dsg.web.modules.exportpwd.entity.table.Export…

如何使用GPT-4o函数调用构建一个实时应用程序?

本教程介绍了如何使用OpenAI最新的LLM GPT-4o通过函数调用将实时数据引入LLM。 我们在LLM函数调用指南(详见https://thenewstack.io/a-comprehensive-guide-to-function-calling-in-llms/)中讨论了如何将实时数据引入聊天机器人和代理。现在,我们将通过将来自Fligh…

bat脚本简介

一、bat脚本 概念定义 BAT 批处理是一种在 Windows 系统中用于将一系列命令组合成一个可执行文件(.bat 文件)的脚本技术。 允许用户将多个操作命令按顺序编写在一起。形成一个自动化执行的流程。批处理文件可以包含各种系统命令和程序调用。 如文件操作…

中国现在最厉害的书法家颜廷利:东方伟大思想家哲学家教育家

中国书法界名人颜廷利教授,一位在21世纪东方哲学、科学界及当代中国教育领域内具有深远影响力的泰斗级人物,不仅以其深厚的国学修为和对易经姓名学的独到见解著称,还因其选择在济南市历城区的龙泉大街以及天桥区的凤凰山庄与泉星小区等地设立…

如何在隔离环境中设置 LocalAI 以实现 GPU 驱动的文本嵌入

作者:来自 Elastic Valeriy Khakhutskyy 你是否想在 Elasticsearch 向量数据库之上构建 RAG 应用程序?你是否需要对大量数据使用语义搜索?你是否需要在隔离环境中本地运行?本文将向你展示如何操作。 Elasticsearch 提供了多种方法…

多曝光融合算法(三)cv2.createAlignMTB()多曝光图像融合的像素匹配问题

文章目录 1.cv2.createAlignMTB() 主要是计算2张图像的位移,假设位移移动不大2.多曝光图像的aline算法:median thresold bitmap原理讲解3.图像拼接算法stitch4.多曝光融合工具箱 1.cv2.createAlignMTB() 主要是计算2张图像的位移,假设位移移动…

Python中猴子补丁是什么,如何使用

1、猴子补丁奇遇记 🐒 在Python的世界深处,隐藏着一种神秘而又强大的技巧——猴子补丁(Monkey Patching)。这是一项允许你在程序运行时动态修改对象(如模块、类或函数)的行为的技术。它得名于其“快速修补…

问题排查: Goalng Defer 带来的性能损耗

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 引言问题背景结论 引言 性能优化之路道阻且长,因为脱敏规定,…

vite常识性报错解决方案

1.导入路径不能以“.ts”扩展名结束。考虑改为导入“xxx.js” 原因:当你尝试从一个以 .ts 结尾的路径导入文件时,ESLint 可能会报告这个错误,因为它期望导入的是 JavaScript 文件(.js 或 .jsx)而不是 TypeScript 文件&…

coap-emqx:使用libcoap与emqx通信

# emqx开启CoAP网关 请参考【https://blog.csdn.net/chenhz2284/article/details/139562749?spm1001.2014.3001.5502】 # 写一个emqx的客户端程序&#xff0c;不断地往topic【server/1】发消息 【pom.xml】 <dependency><groupId>org.springframework.boot<…

开源与新质生产力

在这个信息技术迅猛发展的时代&#xff0c;全球范围内的产业都在经历着深刻的变革。在这样的背景下&#xff0c;“新质生产力”的概念引起了广泛的讨论。无论是已经成为或正努力转型成为新质生产力的企业&#xff0c;都在寻求新的增长动力和竞争优势。作为一名长期从事开源领域…

Linux用户和用户组的管理

目录 前言一、系统环境二、Linux用户组的管理2.1 新增用户组2.2 删除用户组2.3 修改用户组2.4 查看用户组 三、Linux用户的管理3.1 新增用户3.2 删除用户3.3 修改用户3.4 查看用户3.5 用户口令&#xff08;密码&#xff09;的管理 总结 前言 本篇文章介绍如何在Linux系统上实现…

OrangePi Kunpeng Pro深度评测:性能与体验的完美融合

文章目录 一、引言二、硬件开箱与介绍1.硬件清单2.硬件介绍 三、软件介绍四、性能测试1. 功率测试2. cpu测试2.1 单线程cpu测试2.2 多线程cpu测试 五、实际开发体验1. 搭建API服务器2. ONNX推理测试3. 在线推理平台 五、测评总结1. 能与硬件配置2. 系统与软件3. 实际开发体验个…

探索智慧商场的功能架构与应用

在数字化和智能化的浪潮下&#xff0c;智慧商场已经成为零售业的重要发展方向之一。智慧商场系统的功能架构设计与应用&#xff0c;结合了现代信息技术和零售业的实际需求&#xff0c;为商场的管理和运营提供了全新的解决方案。本文将深入探讨智慧商场的功能架构与应用&#xf…

matlab---app

一 基础 标签和信号灯没有回调函数 clc,clear,close all %清理命令区、工作区&#xff0c;关闭显示图形 warning off %消除警告 feature jit off %加速代码运行 ysw{i}i %循环赋值 celldisp(ysw) %显示元胞数组ysw.y1{1}[1,2] …

《软件定义安全》之二:SDN/NFV环境中的安全问题

第2章 SDN/NFV环境中的安全问题 1.架构安全 SDN强调了控制平面的集中化&#xff0c;从架构上颠覆了原有的网络管理&#xff0c;所以SDN的架构安全就是首先要解决的问题。例如&#xff0c;SDN实现中网络控制器相关的安全问题。 1.1 SDN架构的安全综述 从网络安全的角度&…

@BeforeAll 和 @AfterAll 必须是 static 的原因

BeforeAll 和 AfterAll 必须是 static 的原因 执行时机&#xff1a; BeforeAll 方法在所有测试方法之前运行。AfterAll 方法在所有测试方法之后运行。 实例化前/后的执行&#xff1a; 因为 BeforeAll 是在所有测试方法执行之前运行的&#xff0c;所以它在任何一个测试实例创建…

基于springboot的教学管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;教师管理&#xff0c;学生管理&#xff0c;课程管理 教师账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;课程管理&#xff0c;课程表…