线程的深入学习(二)

前言

上一篇讲了线程池的相关知识,这篇文章主要讲解一个
1.并发工具类如CountDownLatch、CyclicBarrier等。
2.线程安全和并发集合:
3.学习如何使用Java提供的线程安全的集合类,如ConcurrentHashMap、CopyOnWriteArrayList等。

并发工具类

  1. CountDownLatch(倒计数器):有两个常用场景
    1.协调子线程结束动作,等待所有子线程运行结束。CountDownLatch允许一个或多个线程等待其他线程完成操作。
    例如,我们很多人喜欢玩的王者荣耀,开黑的时候,得等所有人都上线之后,才能开打
public static void main(String[] args) throws InterruptedException
{ CountDownLatch countDownLatch = new CountDownLatch(5);
Thread 大乔 = new Thread(countDownLatch::countDown);Thread 兰陵王 = new Thread(countDownLatch::countDown);Thread 安其拉 = new Thread(countDownLatch::countDown);Thread 哪吒 = new Thread(countDownLatch::countDown);Thread= new Thread(() -> {
try {
// 稍等,上个卫生间,马上到... Thread.sleep(1500);
countDownLatch.countDown();
} catch (InterruptedException ignored) {}
});
大乔.start();
兰陵王.start();
安其拉.start();
哪吒.start();.start(); countDownLatch.await();
System.out.println("所有玩家已经就位!");
}
  1. 协调线程开始动作,统一各线程开始的时机。
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
Thread 大乔 = new Thread(() -> waitToFight(countDownLatch)); 
Thread 兰陵王 = new Thread(() - > waitToFight(countDownLatch));Thread 安其拉 = new Thread(() ->waitToFight(countDownLatch)); 
Thread 哪吒 = new Thread(() -> waitToFight(countDownLatch));
Thread= new Thread(() -> waitToFight(countDownLatch));
大乔.start();
兰陵王.start();
安其拉.start();
哪吒.start();.start(); Thread.sleep(1000);
countDownLatch.countDown();
System.out.println("敌方还有5秒达到战场,全军出击!");
}private static void waitToFight(CountDownLatch countDownLatch) {
try {
countDownLatch.await(); // 在此等待信号再继续
System.out.println("收到,发起进攻!");
} catch (InterruptedException e)
{ e.printStackTrace();
}
}

countdownlatch核心方法:

  • await():等待latch降为0
  • boolean await(Long Time,TImeUnit unit) : 等待latch降为0,但是设置了超时时间,毕竟不能为了某人等到永久。
  • counDown():latch数量减一
  • getCount():获取当前数量

CyclicBarrier同步屏障

CyclicBarrier的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情就是让一组线程到达一个屏障(也可叫做同步点)时候被阻塞,直到最后一个线程到达屏障的时候,屏障开门,所有的被拦截的线程才会被放行。
和countdownlatch类似,都有协调多线程的结束动作。
不同:countdownlatch的使用是一次性的,无法重复利用,而cyclicBarrier可以重复利用。
最核心的方法是await:如果当前的一个线程不是第一个到达的话,它将会进入等待,直到其他线程都到达,除非发生了被中断,屏障被破除,被拆除,屏障重设等。
在这里插入图片描述

countdownlatch和cyclicBarrier区别点

  • countdownlatch是一次性的,而cyclicBarrier则可以设置多次的屏障,实现重复利用。
  • countdownlatch中的各个子线程不可以等待其他线程执行完毕,只能执行自己的任务,而CyclicBarrier可以等待其他的线程。
    |CyclicBarrier| CountDownLatch|
CyclicBarrierCountDownLatch
CyclicBarrier是可以重复利用的,其中的线程可以等待所有的线程完成任务,这是屏障会拆除,并可以选择性的做一些特定的动作是一次性的,不同的线程在同一个计数器上工作,直到线程为0
是面向线程数的是面向任务数的
再使用 CyclicBarrier时候,必须再构造器中指定参加的线程数,这些线程必须实现await()方法使用Countdownlatch必须要指定任务数,但是这些任务由那些线程完成无关紧要
CyclicBarrier可以再所有线程释放后重复使用COuntdownlatch在计数为0后就不能再使用了
再CyclicBarrier中,如果某个线程遇到中断,超时等问题,那么处于await的线程都会出现问题再COuntdownlatch中一个线程出现问题,不会影响其他线程。

Semaphore(信号量)

semaphore信号量是用来控制同时访问特定的资源的线程数量,通过协调各个线程,以保证合理的使用公共资源。
在这里插入图片描述

一个Semaphore的用途:它可以用于做流量控制,特别是公用资源有限的应用场景,比如数据库连接。

public class SemaphoreTest {
private static final int THREAD_COUNT = 30;
private static ExecutorService threadPool =
Executors.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(10);
public static void main(String[] args) {for (int i = 0; i < THREAD_COUNT; i++){ threadPool.execute(new Runnable() {@Overridepublic void run(){ try {s.acquire();System.out.println("save data");s.release();} catch (InterruptedException e) {}}
});
public class ExchangerTest {
private static final Exchanger<String> exgr = new Exchanger<String>();
private static ExecutorService threadPool = Executors.newFixedThreadPool(2);
public static void main(String[] args) {threadPool.execute(new Runnable(){ @Overridepublic void run(){ try {String A = "银行流水A"; // A录入银行流水数据exgr.exchange(A);}threadPool.shutdown();
}
}在代码中,虽然有30个线程在执行,但是只允许10个并发执行。Semaphore的构造方法 Semaphoreint permits)接受一
个整型的数字,表示可用的许可证数量。 Semaphore10) 表示允许10个线程获取许可证,也就是最大并发数是10Semaphore的用法也很简单,首先线程使用 Semaphoreacquire()方法获取一个许可 证,使用完之后调用release()方
法归还许可证。还可以用tryAcquire()方法尝试获取许可证。

Exchanger交换者

是一个用于线程之间协调协作的工具类,Exchanger用于线程之间的数据交换,他提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。

这两个线程通过 exchange方法交换数据,如果第一个线程先执行exchange()方法,它会一直等待第二个线程也执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。
Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规
则得出2个交配结果。Exchanger也可以用于校对工作,比如我们需要将纸制银行流水通过人工的方式录入成电子银行
流水,为了避免错误,采用AB岗两人进行录入,录入到Excel之后,系统需要加载这两个Excel,并对两个 Excel数据进
行校对,看看是否录入一致

qw

public class ExchangerTest {
private static final Exchanger<String> exgr = new Exchanger<String>();
private static ExecutorService threadPool = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
threadPool.execute(new Runnable()
{ @Override
public void run()
{ try {
String A = "银行流水A"; // A录入银行流水数据
exgr.exchange(A);
} catch (InterruptedException e) {
}
}
});
threadPool.execute(new Runnable() { @Override
public void run() { try {
String B = "银行流水B"; // B录入银行流水数据
String A = exgr.exchange("B");
System.out.println("A和B数据是否一致:" + A.equals(B) + ",A录入的是:" + A + ",B录入是:" + B);
} catch (InterruptedException e) {
}
}
});
threadPool.shutdown();
}
}

假如两个线程有一个没有执行exchange()方法,则会一直等待,如果担心有特殊情况发生,避免一直等待,可以使用
exchange(V x, long timeOut, TimeUnit unit)设置最大等待时长。

总结

本篇主要就是讲了两个并发工具类。Countdownlatch倒计数器和CyclicBarrier同步屏障,以及一个semaphore信号量。

ps:如果可以一键三连,给加点动力。

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

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

相关文章

Linux学习记录——삼십삼 http协议

文章目录 1、URL2、http协议的宏观构成3、详细理解http协议1、http请求2、http响应1、有效载荷格式2、有效载荷长度3、客户端要访问的资源类型4、修改响应写法5、处理不同的请求6、跳转 3、请求方法&#xff08;GET/POST&#xff09;4、HTTP状态码&#xff08;实现3和4开头的&a…

uniapp中用户登录数据的存储方法探究

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;作为一个博主&#xff0c;我们经常需要在应用程序中实现用户登录功能&#xff0c;并且需要将用户的登录数据进行存储&#xff0c;以便在多次使用应用程序时能够方便地获取用户信息。铁蛋通过科技手段帮大家收集整理了些知识&am…

每天五分钟计算机视觉:揭秘迁移学习

本文重点 随着人工智能的迅速发展,深度学习已经成为了许多领域的关键技术。然而,深度学习模型的训练需要大量的标注数据,这在很多情况下是不现实的。迁移学习作为一种有效的方法,可以在已有的数据和模型上进行训练,然后将其应用于新的任务。这种方法大大降低了对新任务的…

嵌入式(一)嵌入式系统介绍 | 嵌入式微处理器,嵌入式系统开发流程,嵌入式系统应用

文章目录 1 嵌入式系统基本介绍1.1 基本概念1.2 嵌入式微处理器分类1.2.1 微控制器MCU1.2.2 微处理器MPU1.2.3 数字信号处理器&#xff08;DSP&#xff09;1.2.4 混合处理器和片上系统&#xff08;SOC&#xff09;1.2.5 可编程片上系统&#xff08;SOPC&#xff09; 1.3 嵌入式…

书香之家 国学启智——学夫堂幼儿国学托管永嘉上塘实验店启航

在教育创新的道路上&#xff0c;学夫堂幼儿国学托管永嘉上塘实验店迎来了一个重要的时刻。经过三个多月的精心筹备和试运营&#xff0c;今天正式宣布学夫堂幼儿国学托管在永嘉县城北街道景和佳苑8幢105号开门迎客。 学夫堂深信&#xff0c;国学智慧不仅是中华文化的瑰宝&#x…

7-34 通讯录的录入与显示 分数 10

文章目录 每日一言题目输入格式&#xff1a;输出格式&#xff1a;输入样例&#xff1a;输出样例&#xff1a; 结语 每日一言 批判的武器当然不能代替武器的批判。 --〈黑格尔法哲学批判〉导言 题目 通讯录中的一条记录包含下述基本信息&#xff1a;朋友的姓名、出生日期、性别…

C++ const 限定符的全面介绍

C const 限定符的全面介绍 1. const 修饰基本数据类型 定义 const 修饰的基本数据类型变量&#xff0c;值不可改变。 语法 const type variable value;特点 不可变性&#xff0c;增加代码可读性。 作用 定义不可修改的常量。 使用场景 全局常量、配置项。 注意事项…

常见函数的4种类型(js的问题)

• 匿名函数 • 回调函数 • 递归函数 • 构造函数 1、匿名函数 定义时候没有任何变量引用的函数 匿名函数自调&#xff1a;函数只执行一次 (function(a, b){console.log(a b);} )(1, 2);// 等价于 function foo (a, b){console.log(a b); }foo(1, …

阿赵UE学习笔记——7、导入资源

阿赵UE学习笔记目录 大家好&#xff0c;我是阿赵。   继续学习虚幻引擎的使用。这次将会把一个带动作和贴图的钢铁侠模型&#xff0c;导入的UE的项目中。 1、准备的资源 这里有2个fbx文件&#xff0c;都是带着网格和动画的&#xff0c;模型网格和骨骼是一样的&#xff0c;只…

MySQL是如何做到可以恢复到半个月内任意一秒的状态的?

MySQL的逻辑架构图 MySQL中两个重要的日志模块&#xff1a;redo log&#xff08;重做日志&#xff09;和binlog&#xff08;归档日志&#xff09; 我们先来看redo log&#xff1a; 介绍一个MySQL里经常说到的WAL技术&#xff0c;即Write-Ahead-Logging&#xff0c;它的关键点…

2023春季李宏毅机器学习笔记 03 :机器如何生成文句

资料 课程主页&#xff1a;https://speech.ee.ntu.edu.tw/~hylee/ml/2023-spring.phpGithub&#xff1a;https://github.com/Fafa-DL/Lhy_Machine_LearningB站课程&#xff1a;https://space.bilibili.com/253734135/channel/collectiondetail?sid2014800 一、大语言模型的两种…

Linux基础知识点(五-信号)

一、信号的基本概念 1.1 信号的概念 信号&#xff08;signal&#xff09;&#xff0c;又称为软中断信号&#xff0c;用于通知进程发生了异步事件&#xff0c;它是Linux系统响应某些条件而产生的一个事件&#xff0c;它是在软件层次上对中断机制的一种模拟&#xff0c;是一种异…

burpsuite模块介绍之extender(扩展)

extender Burp提供了对第三方拓展插件的支持,使用户能够编写自定义插件或从插件商店中安装拓展插件。这些Burp扩展程序可以以多种方式定制Burp的行为,包括修改HTTP请求和响应、自定义UI、添加自定义扫描程序检查以及访问关键的运行时信息,如代理历史记录、目标站点地图和扫…

Spring高手之路-Spring中Bean的五大作用域

目录 Singleton&#xff08;单例&#xff09;&#xff1a;默认的作用域 Prototype&#xff08;原型&#xff09; Request&#xff08;请求&#xff09; Session&#xff08;会话&#xff09; Global Session&#xff08;全局会话&#xff09; 五大作用域范围对比 作用域…

bash 双hash算法sha256的写法

这样是不行的 echo -n "hello" | sha256sum | sha256sum 因为sha256sum的输出有干扰内容 pplde:~/tmp$ echo -n "hello" | sha256sum 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 -需要这样子 echo -n "hello" | sh…

5分钟更新你的图像处理小技巧(1)opencv旋转矩阵的不同之处

力求5分钟直接了当的说明一个实际问题 cv2.getRotationMatrix2D 简介 用于生成图像旋转的仿射变换矩阵 参数包括&#xff1a;center: 旋转的中心点&#xff0c;通常是图像的中心。angle: 旋转角度&#xff0c;以度为单位。正值表示逆时针旋转。scale: 缩放比例&#xff0c;表…

【算法每日一练]-dfs bfs(保姆级教程 篇8 )#01迷宫 #血色先锋队 #求先序排列 #取数游戏 #数的划分

目录 今日知识点&#xff1a; 使用并查集映射点&#xff0c;构造迷宫的连通块 vis计时数组要同步当回合的处理 递归求先序排列 基于不相邻的取数问题&#xff1a;dfs回溯 n个相同球放入k个相同盒子&#xff1a;dfs的优化分支暴力 01迷宫 血色先锋队 求先序排列 取数游…

Javaweb之Mybatis的基础操作的详细解析

1. Mybatis基础操作 学习完mybatis入门后&#xff0c;我们继续学习mybatis基础操作。 1.1 需求 需求说明 通过分析以上的页面原型和需求&#xff0c;我们确定了功能列表&#xff1a; 查询 根据主键ID查询 条件查询 新增 更新 删除 根据主键ID删除 根据主键ID批量删除 …

七:Day06_redis高级01

第一章 Redis入门 1.1 节 什么是NoSql型数据库 NoSQL ,泛指非关系型的数据库, NoSQL Not Only SQL,它可以作为关系型数据库的良好补充。NoSQL 不依赖业务逻辑方式存储&#xff0c;而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。 SQLNoSQL数据结构结构化非…

【K8S 资源管理】声明式资源管理

目录 一、常用的发布方式 1、蓝绿发布&#xff1a; 2、金丝雀发布&#xff08;灰度发布&#xff09;&#xff1a; 3、滚动更新&#xff08;deployment的默认更新方式&#xff09;&#xff1a; 二、声明式管理方法&#xff08;yaml文件&#xff09; 1、三种发布命令&#x…