博客
关于我
JAVA同步屏障CyclicBarrier
阅读量:304 次
发布时间:2019-03-03

本文共 3988 字,大约阅读时间需要 13 分钟。

CyclicBarrier 是 Java 提供的一种同步工具,用于管理多线程程序中的屏障。它允许一组线程在到达屏障时被阻塞,直到最后一个线程到达屏障时,所有被屏障拦截的线程才会继续执行。

1. 简单介绍CyclicBarrier

1.1 功能说明

CyclicBarrier 可以让一组线程在到达屏障时被阻塞,直到最后一个线程到达屏障。所有被屏障拦截的线程只有在最后一个线程到达屏障后才会继续执行。这种机制在多线程计算数据时非常有用,例如计算结果完成后插入同步屏障,阻塞等待所有线程完成。

1.2 类的位置

CyclicBarrier 位于 Java 的 java.util.concurrent 包下。线程在执行 await() 方法后会到达屏障,并等待其他线程也到达屏障。

1.3 构造方法

CyclicBarrier 的构造方法主要有以下两种形式:

  • 传递拦截线程数的参数:
  • public CyclicBarrier(int parties) {    this(parties, null);}
    1. 传递拦截线程数的参数和一个执行的线程任务:
    2. public CyclicBarrier(int parties, Runnable barrierAction) {    if (parties <= 0) throw new IllegalArgumentException();    this.parties = parties;    this.count = parties;    this.barrierCommand = barrierAction;}

      2. 基础使用演示

      2.1 两个线程的示例

      以下是一个简单的两个线程示例,主线程和一个自定义的子线程都执行 await() 方法:

      import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;public class CyclicBarrierTest {    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(2);    public static void main(String[] args) {        new Thread(new Runnable() {            @Override            public void run() {                try {                    cyclicBarrier.await();                } catch (InterruptedException e) {                    e.printStackTrace();                } catch (BrokenBarrierException e) {                    e.printStackTrace();                }                System.out.println("Thread执行");            }        }).start();        try {            cyclicBarrier.await();        } catch (InterruptedException e) {            e.printStackTrace();        } catch (BrokenBarrierException e) {            e.printStackTrace();        }        System.out.println("Main执行");    }}

      2.2 执行结果

      由于 Java 多线程执行顺序由 CPU 随机调度决定,运行结果可能有以下两种情况:

    3. 主线程先于子线程到达屏障,子线程继续等待。
    4. 子线程先于主线程到达屏障,主线程继续等待。
    5. 3. 实战演练

      3.1 场景描述

      假设我们有一个 Excel 文件,保存了一个用户的多个银行账户的银行消费记录。每个工作表(Sheet)对应一个银行卡的消费流水记录。我们需要统计该用户一年内的平均每日银行消费金额。

      3.2 实现思路

      为了提高计算效率,使用多线程分别统计每个工作表的日均消费金额。所有线程完成后,通过 CyclicBarrier 同步,计算出所有账户的日均消费金额,最后得到该用户一年内的日均银行消费金额。

      3.3 可能出现的问题

    6. 如果使用单线程计算,数据量大可能导致效率低下。
    7. 如果不使用 CyclicBarrier,计算时需要等待所有工作表完成,操作不便且容易出错。
    8. 3.4 编码实现

      import java.util.Map;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.Executors;public class BankConsumeFlow implements Runnable {    private static final Integer CPU_NUMBER = Runtime.getRuntime().availableProcessors();    private CyclicBarrier cyclicBarrier = new CyclicBarrier(4, this);    private ConcurrentHashMap
      sheetCount = new ConcurrentHashMap<>(); private void flowCount() { Executor executor = Executors.newFixedThreadPool(CPU_NUMBER); final CountDownLatch latch = new CountDownLatch(CPU_NUMBER); for (int i = 0; i < CPU_NUMBER; i++) { executor.execute(new Runnable() { @Override public void run() { try { int sheetName = Thread.currentThread().getName(); sheetCount.put(sheetName, 100); // 模拟一个工作表的日均流水 cyclicBarrier.await(); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }); } try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } int result = 0; for (Map.Entry
      entry : sheetCount.entrySet()) { result += entry.getValue(); } sheetCount.put("result", result); System.out.println("该用户这一年的银行消费日均为:" + result + "元"); } public static void main(String[] args) { BankConsumeFlow bankConsumeFlow = new BankConsumeFlow(); bankConsumeFlow.flowCount(); }}

      4. 关键方法总结

      4.1 getParties()

      返回 CyclicBarrier 拦截的线程数目。

      4.2 getNumberWaiting()

      返回当前正在阻塞的线程数目(0 到 getParties() - 1)。

      4.3 await()

      线程到达屏障后等待其他线程到达屏障。

      4.4 reset()

      重置计算器,允许线程重新执行。

    转载地址:http://tvll.baihongyu.com/

    你可能感兴趣的文章
    NSRange 范围
    查看>>
    NSSet集合 无序的 不能重复的
    查看>>
    NSURLSession下载和断点续传
    查看>>
    NSUserdefault读书笔记
    查看>>
    NS图绘制工具推荐
    查看>>
    NT AUTHORITY\NETWORK SERVICE 权限问题
    查看>>
    NT symbols are incorrect, please fix symbols
    查看>>
    ntelliJ IDEA 报错:找不到包或者找不到符号
    查看>>
    NTFS文件权限管理实战
    查看>>
    ntko web firefox跨浏览器插件_深度比较:2019年6个最好的跨浏览器测试工具
    查看>>
    ntko文件存取错误_苹果推送 macOS 10.15.4:iCloud 云盘文件夹共享终于来了
    查看>>
    ntp server 用法小结
    查看>>
    ntpdate 通过外网同步时间
    查看>>
    ntpdate同步配置文件调整详解
    查看>>
    NTPD使用/etc/ntp.conf配置时钟同步详解
    查看>>
    NTP及Chrony时间同步服务设置
    查看>>
    NTP服务器
    查看>>
    NTP配置
    查看>>
    NUC1077 Humble Numbers【数学计算+打表】
    查看>>
    NuGet Gallery 开源项目快速入门指南
    查看>>