Java高并发之CyclicBarrier的用法详解
作者:xindoo 发布时间:2023-11-17 16:27:57
Java 中的 CyclicBarrier 是一种同步工具,它可以让多个线程在一个屏障处等待,直到所有线程都到达该屏障处后,才能继续执行。CyclicBarrier 可以用于协调多个线程的执行,以便它们可以在某个点上同步执行。
CyclicBarrier 是 Java 中的一种同步工具,它可以让多个线程在一个屏障点处等待,直到所有线程都到达该点后,才能继续执行。CyclicBarrier 可以用于协调多个线程的执行,以便它们可以在某个点上同步执行。
使用方式
CyclicBarrier 的基本用法如下:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
int n = 3;
CyclicBarrier barrier = new CyclicBarrier(n, new Runnable() {
public void run() {
System.out.println("All threads have reached the barrier");
}
});
Thread t1 = new Thread(new MyRunnable(barrier), "Thread 1");
Thread t2 = new Thread(new MyRunnable(barrier), "Thread 2");
Thread t3 = new Thread(new MyRunnable(barrier), "Thread 3");
t1.start();
t2.start();
t3.start();
}
static class MyRunnable implements Runnable {
private final CyclicBarrier barrier;
public MyRunnable(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is waiting at the barrier...");
barrier.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
在这个例子中,我们创建了一个 CyclicBarrier 对象,它需要等待 3 个线程到达屏障点。当所有线程都到达屏障点后,将会触发一个回调函数,打印一条消息。
我们创建了 3 个线程,并将它们传递给一个自定义的 Runnable 对象。在每个线程的 run 方法中,我们首先打印一条消息,表示线程正在等待屏障点。然后调用 barrier.await() 方法,将线程加入到等待队列中,直到所有线程都到达屏障点后,才会继续执行。在最后,我们打印一条消息,表示线程已经跨过了屏障点。
上面代码的运行结果如下:
Thread 1 is waiting at the barrier...
Thread 3 is waiting at the barrier...
Thread 2 is waiting at the barrier...
All threads have reached the barrier
Thread 2 has crossed the barrier
Thread 1 has crossed the barrier
Thread 3 has crossed the barrier
从上面代码中也可以看出,CyclicBarrier 还支持一个可选的回调函数,在所有的线程都到达屏障点后,会调起指定的回调函数,上述例子中当所有线程到达屏障点的时候,会执行回调函数,表明已经到达屏障点。
CyclicBarrier 还支持一个更高级的用法,即可以在等待线程到达屏障点时,执行一些额外的操作。可以通过 await 方法的返回值来实现这一点,如下所示:
int index = barrier.await();
if (index == 0) {
// 执行额外的操作
}
在这个例子中,await 方法的返回值表示线程在等待队列中的位置,如果返回值为 0,则表示当前线程是最后一个到达屏障点的线程,可以执行一些额外的操作,比如说做一些数据清理之类的收尾工作。
注意事项
在使用 Java 中的 CyclicBarrier 时,需要注意以下几点:
1.CyclicBarrier 的计数器是可重用的,也就是说,当所有线程都到达屏障点后,计数器会被重置为初始值,可以再次使用。如果在等待过程中出现异常,计数器将会被重置,并且所有等待的线程都将会抛出 BrokenBarrierException 异常。
2.如果使用 CyclicBarrier 时,等待的线程数超过了计数器的初始值,将会导致所有线程永远等待下去。因此,在使用 CyclicBarrier 时,需要确保等待的线程数不会超过计数器的初始值。
3.CyclicBarrier 的回调函数是在最后一个线程到达屏障点时执行的,因此,在回调函数中执行的操作应该是线程安全的,否则可能会导致不可预期的结果。
4.CyclicBarrier 可以用于协调多个线程的执行,以便它们可以在某个点上同步执行。**但是,如果线程之间的执行顺序对于程序的正确性很重要,那么 CyclicBarrier 可能不是最好的选择。**在这种情况下,可能需要使用其他同步工具,如 CountDownLatch 或 Semaphore。
5.CyclicBarrier 的性能可能会受到等待线程的数量和计数器的初始值的影响。**如果等待线程的数量很大,或者计数器的初始值很大,那么可能会导致性能下降。**因此,在使用 CyclicBarrier 时,需要根据实际情况进行调整。
总之,在使用 Java 中的 CyclicBarrier 时,需要仔细考虑各种情况,以确保程序的正确性和性能。
来源:https://juejin.cn/post/7209617649885184058
猜你喜欢
- 把做工程过程常用的一些代码段做个记录,下面代码是关于Java实现图片倒影的的代码,应该对大家有较大用处。 public class
- Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。本篇不涉及其原理,只用代码构建项目简单试用一下其回滚
- 本文实例讲述了java取两个字符串的最大交集的实现方法,分享给大家供大家参考。具体实现方法如下:package com.itheima.ne
- Spring * 监测每个Controller或方法的执行时长首先写一个类(TestInterceptor)让他继承HandlerInter
- 概述关于 static 关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的。也就是说,既
- 前言项目使用了SpringBoot构建项目。下面对动态调整日志的级别进行记录。从版本 1.5.1 之后就提供了基于 spring-boot-
- 本文实例讲述了java在网页上面抓取邮件地址的方法。分享给大家供大家参考。具体实现方法如下:import java.io.BufferedR
- Accessors翻译是存取器。通过该注解可以控制getter和setter方法的形式。 @Accessors(fluent = true)
- 由于CPU的计算频率非常高,每秒计算数十亿次,因此可以将CPU的时间从毫秒的维度进行分段,每一小段叫作一个CPU时间片。目前操作系统中主流的
- java jdbc连接和使用jdbc导入驱动//jar是已经打包好的class文件集,可以引用到其他工程中 //Build Pa
- jQuery的方法连缀使用起来非常方便,可以简化语句,让代码变得清晰简洁。那C#的类方法能不能也实现类似的功能呢?基于这样的疑惑,研究了一下
- 本文实例讲述了C#编程实现四舍五入、向上及下取整的方法。分享给大家供大家参考,具体如下:在处理一些数据时,我们希望能用“四舍五入”法实现,但
- ThreadLocal简介变量值的共享可以使用public static的形式,所有线程都使用同一个变量,如果想实现每一个线程都有自己的共享
- 表:需求:将表中的数据,按照一级二级分类返回给前端json数据代码实现:java代码: public class ResultIndustr
- 说到Java的本地存储,肯定使用IO流进行操作。首先,我们需要一个创建文件的函数createNewFile:public static bo
- 缘起年前,因为项目需要进行配置的优化和架构的升级,领导给我来了个任务,让我去进行技术调研需要将配置中心的yaml配置文件里面的配置转为Jso
- 枚举是 C# 中最有意思的一部分,大部分开发人员只了解其中的一小部分,甚至网上绝大多数的教程也只讲解了枚举的一部分。那么,我将通过这篇文章向
- MyBatis添加记录后获取主键ID,这是一个很常见的需求。这个需求有分为两种情况:(1)添加单条记录时获取主键值;(2)获取批量添加记录时
- 一、前期准备我们要在IDEA上创建一个新的项目,创建好一个项目后,我们需要创建4个包,分别是英雄包,装备包,铭文包,野怪包,皮肤包然后我们就
- 1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是如果有Synchr