【Java多线程】4——特定场景解决办法

4 特定场景解决方法

⭐⭐⭐⭐⭐⭐
Github主页👉https://github.com/A-BigTree
笔记仓库👉https://github.com/A-BigTree/tree-learning-notes
个人主页👉https://www.abigtree.top
⭐⭐⭐⭐⭐⭐


如果可以,麻烦各位看官顺手点个star~😊

如果文章对你有所帮助,可以点赞👍收藏⭐支持一下博主~😆


文章目录

  • 4 特定场景解决方法
    • 4.1 `CountDownLatch`
      • 实例
    • 4.2 `CyclicBarrier`
      • 实例
    • 4.3 `Semaphore`
      • 4.3.1 常规方式使用
      • 4.3.2 引入超时机制
      • 4.3.3 应用场景举例
    • 4.4 `Fork Join`
      • 4.4.1 介绍
      • 4.4.2 API介绍
        • `RescursiveTask`
        • `ForkJoinTask`
      • 4.4.3 案例
        • 需求
        • 代码

4.1 CountDownLatch

效果:指定一个操作步骤数量,在各个子线程中,每完成一个任务就给步骤数量 - 1;在步骤数量减到0之前,CountDownLatch 可以帮我们把最后一步操作抑制住(阻塞),让最后一步操作一直等到步骤被减到 0 的时候执行。

实例

有六名同学在值日,班长负责锁门。班长必须确保所有同学都离开教室再锁门。

// 声明一个变量,用来保存同学的数量
int stuNum = 6;// 创建CountDownLatch对象
CountDownLatch countDownLatch = new CountDownLatch(stuNum);// 创建和同学数量相等的线程
for (int i = 0; i < stuNum; i++) {String num = String.valueOf(i + 1);new Thread(()->{// 完成一次操作System.out.println(Thread.currentThread().getName() + " " + num + "号同学离开教室");// 让countDownLatch管理的数量-1countDownLatch.countDown();}).start();}// 让countDownLatch负责将最后一步操作抑制住
countDownLatch.await();System.out.println("班长锁门");

4.2 CyclicBarrier

支持多线程在执行各自任务的时候,到达某个状态点就等待,等所有线程都到达这个状态点再继续执行后步骤。

实例

public class DemoO19CyclicBarrierTest {private static List<List<String>> matrix = new ArrayList<>();static {matrix.add(Arrays.asList("normal","special","end"));matrix.add(Arrays.asList("normal","normal","special","end"));matrix.add(Arrays.asList("normal","normal","normal","special","end"));}public static void main(String[] args) {// 1.创建CyclicBarrier对象CyclicBarrier barrier = new CyclicBarrier(3);// 2.创建3个线程分别执行各自的任务new Thread(()->{try {List<String> list = matrix.get(0);for (String value : list) {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() + " value = " + value);if ("special".equals(value)) {// 遇到特殊任务标记,就让当前线程等一下barrier.await();}}} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, "thread01").start();new Thread(()->{try {List<String> list = matrix.get(1);for (String value : list) {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() + " value = " + value);if ("special".equals(value)) {// 遇到特殊任务标记,就让当前线程等一下barrier.await();}}} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, "thread02").start();new Thread(()->{try {List<String> list = matrix.get(2);for (String value : list) {TimeUnit.SECONDS.sleep(1);System.out.println(Thread.currentThread().getName() + " value = " + value);if ("special".equals(value)) {// 遇到特殊任务标记,就让当前线程等一下barrier.await();}}} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, "thread03").start();}}

4.3 Semaphore

4.3.1 常规方式使用

使用 Semaphore 可以帮助我们管理资源位;当某个线程申请资源时,由 Semaphore 检查这个资源是否可用;如果其他线程释放了这个资源,那么申请资源的线程就可以使用。

// 1、创建 Semaphore 对象,指定资源数量为 3
Semaphore semaphore = new Semaphore(3);// 2、创建 10 个线程争夺这 3 个资源
for (int i = 0; i < 10; i++) {new Thread(() -> {try {// 申请资源semaphore.acquire();// 拿到资源执行操作System.out.println("【" + Thread.currentThread().getName() + "】号车辆【驶入】车位");TimeUnit.SECONDS.sleep(3);System.out.println("【" + Thread.currentThread().getName() + "】号车辆【驶出】车位");} catch (InterruptedException e) {e.printStackTrace();} finally {// 操作完成释放资源semaphore.release();}}, i + "").start();
}

4.3.2 引入超时机制

// 1、设定车位数量
int carPositionCount = 3;// 2、创建 Semaphore 对象
Semaphore semaphore = new Semaphore(carPositionCount);// 3、创建 50 个线程抢车位
for (int i = 0; i < 50; i++) {int carNum = i;new Thread(()->{boolean acquireResult = false;try {// 线程开始时先申请资源,申请不到会进入等待状态// 申请资源方式一:不见不散,等不到资源就一直等// semaphore.acquire();// 申请资源方式二:过时不候acquireResult = semaphore.tryAcquire(3, TimeUnit.SECONDS);if (acquireResult) {// 申请到资源时,线程会继续执行System.out.println(carNum + "号车辆驶入车位");// 车辆在车位停放一段时间TimeUnit.SECONDS.sleep(2);// 停放完成离开车位System.out.println(carNum + "号车辆驶出车位");} else {System.out.println(carNum + "号车辆放弃等待");}} catch (Exception e) {e.printStackTrace();} finally {// 判断当前线程释放拿到了资源if (acquireResult) {// 任务执行完成释放资源semaphore.release();}}}).start();}    

4.3.3 应用场景举例

借助Semaphore实现『限流』操作。

  • 当前服务器实例能够承受多大的访问量——设置为资源的数量。
  • 根据资源的数量创建Semaphore对象。
  • 服务器实例接收到请求通过Semaphore对象管理处理请求数量。
    • 在能力范围内:处理请求。
    • 超过能力范围:设定等待时间,看是否能够得到别的请求处理完成释放资源。

4.4 Fork Join

4.4.1 介绍

使用 Fork Join 框架能够帮助我们把一个大型任务,根据一定规律,拆分成小任务执行。如果拆分后的任务还不够小,可以以递归模式继续拆分,直到拆分到可以执行的程度。然后再把各个子任务执行的结果汇总到一起。

  • Fork:拆分:把大任务拆分成小任务。
  • Join:合并:把小任务执行的结果合并到一起。

在这里插入图片描述

4.4.2 API介绍

RescursiveTask

在这里插入图片描述

我们使用 Fork Join 框架只需要继承 RecursiveTask,然后重写 compute() 方法即可。在 compute() 方法中需要包含:

  • 任务拆分的逻辑
  • 任务拆分的操作:调用 fork() 方法
  • 已拆分任务的合并:调用 join() 方法
  • 子任务结果的合并:将 join() 方法的返回值合并起来
ForkJoinTask

ForkJoinTask 类是 RecursiveTask 的父类。

在这里插入图片描述

4.4.3 案例

需求

完成从 1~100 的累加。

代码
// 任务类
class MyTask extends RecursiveTask {// 区间开始位置private int begin;// 区间结束位置private int end;// 区间调整值:要通过拆分任务将区间调整到 10 以内public static final int ADJUST_VALUE = 10;// 保存当前任务的结果private int result = 0;// 声明构造器,设定当前任务的开始和结束位置public MyTask(int begin, int end) {this.begin = begin;this.end = end;}@Overrideprotected Object compute() {// 1、判断当前区间是否是原子任务中可以执行计算的范围if (end - begin <= ADJUST_VALUE) {for (int i = begin; i <= end ; i++) {result  = result + i;}} else {// 2、计算新拆分任务的区间范围int leftBegin = begin;int leftEnd = (begin + end) / 2;int rightBegin = leftEnd + 1;int rightEnd = end;// 3、创建两个新的任务(子任务)MyTask myTaskLeft = new MyTask(leftBegin, leftEnd);MyTask myTaskRight = new MyTask(rightBegin, rightEnd);// 4、调用框架提供的 fork() 进一步拆分任务myTaskLeft.fork();myTaskRight.fork();// 5、调用框架提供的 join() 获取子任务计算的结果int leftResult = (int) myTaskLeft.join();int rightResult = (int) myTaskRight.join();// 6、把子任务的结果合并到一起result = leftResult + rightResult;}return result;}}// 测试代码
// 1、创建 Fork Join 任务池
ForkJoinPool pool = new ForkJoinPool();// 2、创建任务对象
MyTask myTask = new MyTask(1, 100);// 3、将任务对象提交到任务池
ForkJoinTask forkJoinTask = pool.submit(myTask);// 4、获取任务执行结果
int finalResult = (int) forkJoinTask.get();System.out.println("finalResult = " + finalResult);

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

C语言结合体和枚举的魅力展现

前言 ✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱’博客 所属栏目&#xff1a;人工智能 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 引言: 前面我们已经讲了结构体的声明&#xff0c;自引用&#xff0c;内存…

排序C++

题目 法1 sort升序排序&#xff0c;再逆序输出 #include<iostream> #include<algorithm> using namespace std;const int N 5e53;//注意const&#xff0c;全局 int a[N]; int main() {//错误int N5e53;//错误const int a[N];int n;cin >> n;for (int i 1;…

【数据结构】新篇章 -- 顺序表

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

【数据结构】顺序表习题之移除元素和合并两个有效数组

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《数据结构》 &#x1f389;道阻且长&#xff0c;行则将至 前言 嗨呀&#xff0c;今天的博客是关于顺序表的两道题目&#xff0c;是力扣的移除元素和合并有序数组的题目。 一.移除…

EXCEL通过VBA字典快速分类求和

EXCEL通过VBA字典快速分类求和 汇总截图 Option ExplicitOption Explicit Sub answer3() Dim wb As Workbook Dim sht As Worksheet Set wb ThisWorkbook Set sht wb.Worksheets(2) Dim ss1 As Integer Dim ss2 As Integer Dim i As Integer Dim j As Integer j 1Dim aa()…

人工智能:数字化转型中的关键角色

人工智能&#xff1a;数字化转型中的关键角色 数字化转型是十多年来商业变革的核心&#xff0c;它本身也在人工智能的崛起中发生转变。人工智能有望极大地改变数字化转型&#xff0c;从企业设定的目标到从业者用来推进计划的工具。本文将深入探讨人工智能在数字化转型中的扮演的…

Transformers —— 以通俗易懂的方式解释-Part 1

公众号:Halo咯咯,欢迎关注~ 本系列主要介绍了为ChatGPT以及许多其他大型语言模型(LLM)提供支持的Transformer神经网络。我们将从基础的Transformer概念开始介绍,尽量避免使用数学和技术细节,使得更多人能够理解这一强大的技术。 Transformers —— 以通俗易懂的方式解释…

pip永久修改镜像地址

修改命令&#xff1a; pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/ 效果&#xff1a; 会在C:\Users\PC(用户名)\AppData\Roaming\pip目录下新增或修改文件pip.ini 文件内容&#xff1a; [global] index-url https://pypi.tuna.tsinghua.e…

关于web_server项目的学习记录(自用)

主要参考资料&#xff1a; 我在地铁吃闸机 基础处理框架&#xff1a;Multi-reactor muduo库有三个核心组件实现持续监听reactor的fd&#xff1a;channel;epoll/poller/eventloop类 channel 事件监听器epoll_ctl监听到了fd发生了什么事件,channel类会封装每个fd和fd感兴趣的事…

9、鸿蒙学习-开发及引用静态共享包(API 9)

HAR&#xff08;Harmony Archive&#xff09;是静态共享包&#xff0c;可以包含代码、C库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP&#xff0c;不能独立安装运行在设备上&#xff0c;只能作为应用模块的依赖项被引用。…

ethers.js:sign(签名)

Signers 在ethers中Signer是以太坊账户的抽象&#xff0c;可以用来签名消息和交易&#xff0c;如将签名的交易发送到以太坊网络以执行状态更改的操作。 npm install ethers5.4.0// 引入 import { ethers } from ethers签名 this.provider new ethers.providers.Web3Provider(…

36.not comply with the UI component syntax不允许在UI描述里直接使用

不允许在UI描述里直接使用&#xff0c;但可以在方法或者函数里使用 not comply with the UI component syntax. <etsLint> 这里ok:

搜索与图论——Floyd算法求最短路

floyd算法用来求多源汇最短路 用邻接矩阵来存所有的边 时间复杂度O(n^3) #include<iostream> #include<cstring> #include<algorithm>using namespace std;const int N 20010,INF 1e9;int n,m,k; int g[N][N];void floyd(){for(int k 1;k < n;k ){f…

Python-基础部署

机器没法直接读懂我们写的代码&#xff0c;需要解释解释器作为中间的翻译&#xff0c;把代码转换成字节码在执行 安装python解释器 Download Python | Python.org 安装代码编辑器 pycharm Thank you for downloading PyCharm! 创建一个项目&#xff0c;每个项目里的文件夹…

一周学会Django5 Python Web开发-Django5模型定义

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计41条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

Windows无法安装torch==1.4.0

在conda中&#xff0c;每创建一个虚拟环境&#xff0c;就要重新配置其中的pytorch 这次我创建的虚拟环境需要torch1.4.0的版本。 torch网址&#xff1a;https://pytorch.org/get-started/previous-versions/ 解决办法 按以下代码进行安装&#xff1a; pip install torch0.4.0…

【MySQL探索之旅】MySQL数据表的增删查改——约束

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

工业项目中你连IIoT系统都没见过?

什么是IIoT 工业物联网&#xff08;IIoT&#xff09;是信息技术和制造业融合的产物&#xff0c;利用物联网技术连接工业设备、传感器、系统和人员&#xff0c;实现工业生产数字化、智能化、自动化。IIoT提升生产效率、品质、减低成本和资源利用&#xff0c;打造智能化工业。 功…

知识图谱与大数据:区别、联系与应用

目录 前言1 知识图谱1.1 定义1.2 特点1.3 应用 2 大数据2.1 定义2.2 应用 3. 区别与联系3.1 区别3.2 联系 结语 前言 在当今信息爆炸的时代&#xff0c;数据成为了我们生活和工作中不可或缺的资源。知识图谱和大数据是两个关键概念&#xff0c;它们在人工智能、数据科学和信息…

小程序英文口语发音评测

一、英文口语评测需求 在全球化的今天&#xff0c;英语已经成为了世界上最重要的国际语言之一。无论是在国际商务、科技研究、教育还是日常生活中&#xff0c;英语都扮演着举足轻重的角色。因此&#xff0c;掌握英文口语的能力对于个人的职业发展、学术研究以及跨文化交流都具…