线程的深入学习(二)

前言

上一篇讲了线程池的相关知识,这篇文章主要讲解一个
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…

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

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

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

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

阿赵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;它的关键点…

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; 五大作用域范围对比 作用域…

【算法每日一练]-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…

数据结构第2章 栈和队列

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 本篇笔记整理&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 0、思维导图栈和队列1、栈1&#xff09;特点2&#xff0…

技术资讯:Vue 3.4 新版本发布,1分钟快速看看改了啥!

大家好&#xff0c;我是大澈&#xff01; 本文约1000字&#xff0c;整篇阅读大约需要1分钟。 感谢关注微信公众号&#xff1a;“程序员大澈”&#xff0c;免费领取"面试礼包"一份&#xff0c;然后免费加入问答群&#xff0c;从此让解决问题的你不再孤单&#xff01…

SpringMVC框架

SpringMVC 三层架构MVC模式SpringMVC入门案例总结 三层架构 表现层&#xff08;web&#xff09; 页面数据的收集&#xff0c;产出页面 业务逻辑层&#xff08;service&#xff09; 业务处理 数据访问层&#xff08;Dao&#xff09; 数据持久化 MVC模式 SpringMVC 基于Java…

单元测试框架-Unittest

1 Selenium自动化测试基础和环境部署 1.Web功能自动化测试——为什么要学习单元测试框架unittest?除此之外还有没有其他的单元测试框架&#xff1f; Python语言编写的WebDriver测试脚本通常使用单元测试框架来运行&#xff0c;所以&#xff0c;了解单元测试框架的基本方法和…

【日积月累】Java Lambda 表达式

目录 【日积月累】Java Lambda 表达式 1.前言2.语法3.应用场景3.1简化匿名内部类的编写3.1简化匿名内部类的编写3.2简化集合类中的操作3.3实现函数式接口3.4简化多个方法的调用3.5简化异步编程 4.总结5.参考 文章所属专区 日积月累 1.前言 Lambda表达式是一个匿名函数&#…

useState和setState区别

一、主要是讲一下类组件的状态和函数组件的状态 1.类组件中state只能有一个&#xff0c; 函数组件中state可以有多个 函数组件&#xff1a;可以使用对个状态&#xff0c;便于控制。 // 文章数量的初始值const [articleData, setArticleData] useState({list: [],// 文章列表…

k8s 之7大CNI 网络插件

一、介绍 网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求&#xff0c;但在实现方面也具有一定的灵活性。因此&#xff0c;业界已有不少不同的网络方案&#xff0c;来满足特定的环境和要求。 CNI意为容器网络…