5.5. Java并发工具类(如CountDownLatch、CyclicBarrier等)
5.5.1 CountDownLatch
CountDownLatch
是一个同步辅助类,它允许一个或多个线程等待,直到其他线程完成一组操作。CountDownLatch
有一个计数器,当计数器减为0时,等待的线程将被唤醒。计数器只能减少,不能增加。
示例:使用CountDownLatch等待所有线程完成任务
假设我们有一个任务需要三个子任务完成,我们可以使用CountDownLatch
来等待所有子任务完成。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 1; i <= 3; i++) {
final int taskNumber = i;
new Thread(() -> {
System.out.println("Task " + taskNumber + " started");
try {
Thread.sleep(1000 * taskNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task " + taskNumber + " completed");
latch.countDown();
}).start();
}
System.out.println("Waiting for all tasks to complete...");
latch.await();
System.out.println("All tasks completed");
}
}
在这个示例中,我们创建了一个CountDownLatch
并设置初始计数器为3。每个子任务完成后,调用latch.countDown()
减少计数器。主线程调用latch.await()
等待所有子任务完成。
5.5.2 CyclicBarrier
CyclicBarrier
是一个同步辅助类,它允许一组线程相互等待,直到所有线程都准备好继续执行。当所有线程都到达屏障点时,屏障将打开。CyclicBarrier
可以重复使用。
示例:使用CyclicBarrier同步多个线程
假设我们有三个线程需要在某个点同步,我们可以使用CyclicBarrier
实现这个目的。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads are ready to proceed"));
for (int i = 1; i <= 3; i++) {
final int taskNumber = i;
new Thread(() -> {
System.out.println("Task " + taskNumber + " is ready");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("Task " + taskNumber + " is proceeding");
}).start();
}
}
}
在这个示例中,我们创建了一个CyclicBarrier
并设置参与者数量为3。每个线程在准备好继续执行之前调用barrier.await()
。当所有线程都准备好时,屏障将打开,所有线程将继续执行。
5.5.3 Semaphore
Semaphore
是一个计数信号量,它维护了一个许可集。线程可以请求许可,如果有可用的许可,线程将获得许可并继续执行。否则,线程将阻塞,直到有可用的许可。许可可以由任何线程释放。Semaphore
可用于实现资源池、限制并发访问等。
示例:使用Semaphore限制并发访问
假设我们有一个只能同时处理三个请求的服务器,我们可以使用Semaphore
来实现并发访问限制。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 10; i++) final int clientNumber = i;
new Thread(() -> {
try {
System.out.println("Client " + clientNumber + " is trying to connect");
semaphore.acquire();
System.out.println("Client " + clientNumber + " is connected");
Thread.sleep(2000);
System.out.println("Client " + clientNumber + " is disconnected");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
}
}
}
在这个示例中,我们创建了一个Semaphore
并设置初始许可数量为3。每个客户端线程在连接服务器之前调用semaphore.acquire()
请求许可。当许可可用时,线程将获得许可并继续执行。线程完成后,调用semaphore.release()
释放许可。
5.5.4 Exchanger
Exchanger
是一个同步辅助类,它允许两个线程在一个临界点交换数据。当两个线程都到达交换点时,它们将交换数据。Exchanger
可以用于遗传算法、管道设计等。
示例:使用Exchanger交换数据
假设我们有两个线程,一个生成数据,另一个处理数据。我们可以使用Exchanger
在这两个线程之间交换数据。
import java.util.concurrent.Exchanger;
public class ExchangerExample {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
try {
String data = "Data from producer";
System.out.println("Producer is sending: " + data);
String receivedData = exchanger.exchange(data);
System.out.println("Producer received: " + receivedData);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
String data = "Data from consumer";
System.out.println("Consumer is sending: " + data);
String receivedData = exchanger.exchange(data);
System.out.println("Consumer received: " + receivedData);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
在这个示例中,我们创建了一个Exchanger
。生产者和消费者线程在交换数据前调用exchanger.exchange(data)
。当两个线程都到达交换点时,它们将交换数据。
5.5.5 Phaser
Phaser
是一个灵活的同步辅助类,它允许一组线程相互等待,直到所有线程都准备好继续执行。与CyclicBarrier
类似,但Phaser
更加灵活,可以动态调整参与者数量和支持多个阶段。
示例:使用Phaser同步多个线程
假设我们有三个线程需要在某个点同步,我们可以使用Phaser
实现这个目的。
import java.util.concurrent.Phaser;
public class PhaserExample {
public static void main(String[] args) {
Phaser phaser = new Phaser(3);
for (int i = 1; i <= 3; i++) {
final int taskNumber = i;
new Thread(() -> {
System.out.println("Task " + taskNumber + " is ready");
phaser.arriveAndAwaitAdvance();
System.out.println("Task " + taskNumber + " is proceeding");
}).start();
}
}
}
在这个示例中,我们创建了一个Phaser
并设置参与者数量为3。每个线程在准备好继续执行之前调用phaser.arriveAndAwaitAdvance()
。当所有线程都准备好时,屏障将打开,所有线程将继续执行。
这些并发工具类为Java多线程编程提供了强大的支持,帮助我们更轻松地实现各种同步和并发场景。希望这些示例能帮助你理解并掌握这些工具类的用法。
推荐阅读:
https://mp.weixin.qq.com/s/dV2JzXfgjDdCmWRmE0glDA
https://mp.weixin.qq.com/s/an83QZOWXHqll3SGPYTL5g
5.5. Java并发工具类(如CountDownLatch、CyclicBarrier等)的更多相关文章
- 【Java并发工具类】CountDownLatch和CyclicBarrier
前言 下面介绍协调让多线程步调一致的两个工具类:CountDownLatch和CyclicBarrier. CountDownLatch和CyclicBarrier的用途介绍 CountDownLat ...
- Java并发工具类之CountDownLatch
CountDownLatch允许一个或则多个线程等待其他线程完成操作. 假如我们有这样的需求:我们需要解析一个excel文件中的多个sheet,我们可以考虑使用多线程,每一个线程解析excel中的一个 ...
- java 并发工具类CountDownLatch & CyclicBarrier
一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...
- Java并发工具类 - CountDownLatch
Java并发工具类 - CountDownLatch 1.简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurrent包下面 http: ...
- 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger
1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...
- Java并发工具类CountDownLatch源码中的例子
Java并发工具类CountDownLatch源码中的例子 实例一 原文描述 /** * <p><b>Sample usage:</b> Here is a pai ...
- 并发工具类:CountDownLatch、CyclicBarrier、Semaphore
在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...
- 基于AQS实现的Java并发工具类
本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...
- JAVA并发工具类---------------(CountDownLatch和CyclicBarrier)
CountDownLatch是什么 CountDownLatch,英文翻译为倒计时锁存器,是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 闭锁可以延迟线程的进 ...
- 线程并发工具类之CountDownLatch的使用及原理分析
原文链接:http://www.studyshare.cn/blog/details/1149/1 java开发工具下载地址及安装教程大全,点这里.更多技术文章,在这里. 一.定义 CountDown ...
随机推荐
- 组合计数中的q-模拟 q analog
拒绝更新,深度和广度上建议看这个pdf URL里面用到的一些query-string过期了,,, 论文题目是 THE q-SERIES IN COMBINATORICS; PERMUTATION ST ...
- 第四朵“云”!全托管的时序数据云平台 TDengine Cloud 正式支持阿里云
3 月 13 日,全托管的时序数据处理云服务平台 TDengine Cloud 正式支持阿里云,这是继 Microsoft Azure.AWS.Google Cloud 后 TDengine Clou ...
- MySQL高性能索引策略和查询性能优化
前缀索引和索引选择性 有时候需要索引很长的字符,这会让索引变得大且慢.一个策略是模拟哈希索引. 通常可以索引开始的部分字符,这样可以大大解约索引空间,提高索引效率.但这样会降低索引的选择性. 索引的选 ...
- php实现微信小程序消息通知
大家好,又见面了,我是你们的朋友全 接入消息通知指引地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/callback_help.h ...
- easy-excel读取远程地址获得文件进行上传
背景 作为一个快五年的程序员,一直以来还没有自己维护过自己的技术栈,最近也是有时间,所以也是下定决心,从头开始,一步一步的夯基础.最近在系统化的学习easy-excel,今天遇到了一个问题,特意记录一 ...
- [PKM]阅读的方法
0 概述 数据 => 信息 => 知识 => 智慧 1 读书的目的 : 先寻求真理,而后实践 => 先博学,而后守约(读透) & 先泛读/速读,再精读 / 知行合一 年 ...
- 【论文阅读笔记】Class-Incremental Learning with Strong Pre-trained Models
Key_words: Continual learning, strong pretrained model, fix, fusion Create_time: April 14, 2022 6:32 ...
- Java Heap
堆 堆是一种基于树的数据结构,是一种完全二叉树,堆中的所有的节点都按照特定的顺序排列. 在堆数据结构中,如果任意父节点的值都大于其子节点,则会产生一个大顶堆:反之,如果任意父节点的值都小于其子节点,则 ...
- PHPCMSV9 单文件上传功能代码
后台有"多文件上传"功能,但是对于有些情况,我们只需要上传一个文件,而使用多文件上传功能上传一个文件,而调用时调用一个文件太麻烦了. 所以我就自己动手,参考其他字段类型的网站,研究 ...
- AspNetCore 成长杂记(一):JWT授权鉴权之生成JWT(其一)
引子 最近不知怎么的,自从学了WebAPI(为什么是这个,而不是MVC,还不是因为MVC的Razor语法比较难学,生态不如现有的Vue等框架,webapi很好的结合了前端生态)以后,使用别人的组件一帆 ...