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等)的更多相关文章

  1. 【Java并发工具类】CountDownLatch和CyclicBarrier

    前言 下面介绍协调让多线程步调一致的两个工具类:CountDownLatch和CyclicBarrier. CountDownLatch和CyclicBarrier的用途介绍 CountDownLat ...

  2. Java并发工具类之CountDownLatch

    CountDownLatch允许一个或则多个线程等待其他线程完成操作. 假如我们有这样的需求:我们需要解析一个excel文件中的多个sheet,我们可以考虑使用多线程,每一个线程解析excel中的一个 ...

  3. java 并发工具类CountDownLatch & CyclicBarrier

    一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...

  4. Java并发工具类 - CountDownLatch

    Java并发工具类 - CountDownLatch 1.简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurrent包下面 http: ...

  5. 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger

    1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...

  6. Java并发工具类CountDownLatch源码中的例子

    Java并发工具类CountDownLatch源码中的例子 实例一 原文描述 /** * <p><b>Sample usage:</b> Here is a pai ...

  7. 并发工具类:CountDownLatch、CyclicBarrier、Semaphore

    在多线程的场景下,有些并发流程需要人为来控制,在JDK的并发包里提供了几个并发工具类:CountDownLatch.CyclicBarrier.Semaphore. 一.CountDownLatch ...

  8. 基于AQS实现的Java并发工具类

    本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...

  9. JAVA并发工具类---------------(CountDownLatch和CyclicBarrier)

    CountDownLatch是什么 CountDownLatch,英文翻译为倒计时锁存器,是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 闭锁可以延迟线程的进 ...

  10. 线程并发工具类之CountDownLatch的使用及原理分析

    原文链接:http://www.studyshare.cn/blog/details/1149/1 java开发工具下载地址及安装教程大全,点这里.更多技术文章,在这里. 一.定义 CountDown ...

随机推荐

  1. JUC——CountDownLatch/CyclicBarrier/Semaphore

    系统性学习,异步IT-BLOG CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用).CountDownLatch 能够使一个线 ...

  2. react之点语法(利用函数组件)

    index.js import React, { Component } from 'react' import MyCom from './MyCom'; export default class ...

  3. KVM WEB管理工具 WebVirtMgr

    一.webvirtmgr介绍及环境说明 温馨提示:安装KVM是需要2台都操作的,因为我们是打算将2台都设置为宿主机所有都需要安装KVM相关组件 github地址https://github.com/r ...

  4. day12:闭包函数&匿名函数(lambda)

    闭包函数 闭包函数的定义: 如果内函数使用了外函数的局部变量并且外函数把内函数返回出来的过程 叫做闭包里面的内函数是闭包函数 一个简单的闭包函数示例: def songyunjie_family(): ...

  5. MySQL(八)哈希索引、AVL树、B树与B+树的比较

    Hash索引 简介 ​ 这部分略了 Hash索引效率高,为什么还要设计索引结构为树形结构? Hash索引仅能满足 =.<>和IN查询,如果进行范围查询,哈希的索引会退化成O(n):而树型的 ...

  6. 解决flex布局中justify-content设置成space-between后因数据问题导致最后一行布局错乱

    在常用的flex布局中,当页面展示商品时,因为数据的不确定,导致justify-content设置成space-between,最后一行布局错乱 1 <!DOCTYPE html> 2 & ...

  7. Kubernetes入门实践(Pods)

    为了解决多应用联合运行的问题,同时还要不破坏容器的隔离,就要再对多个容器进行打包.Pod就是对容器的打包,里面的容器可以看成是一个整体,总是能一起调度.一起运行,绝不会出现分离的情况,而Pod属于Ku ...

  8. Go语言实现协程下载器

    一般常用的下载方式是通过浏览器访问URL,然后基于HTTP进行下载.这种单线程下载方式通常比较慢,这里尝试使用Go语言实现一个多协程的下载器. 大致思路 按照传统的单线程的思路,实现下载要基于HTTP ...

  9. 【Vue2.x源码系列06】计算属性computed原理

    上一章 Vue2异步更新和nextTick原理,我们介绍了 JavaScript 执行机制是什么?nextTick源码是如何实现的?以及Vue是如何异步更新渲染的? 本章目标 计算属性是如何实现的? ...

  10. Docker构建镜像踩坑日记

    从Github上拉取python项目后,运行dockerfile构建镜像失败,一步步查找原因 主要原因就是国内下载各种依赖超时,以下提供pip.apt.pipenv镜像解决方案 pip更换国内镜像 这 ...