并发设计模式实战系列(16):屏障(Barrier)

news2025/5/11 0:41:06

🌟 大家好,我是摘星! 🌟

今天为大家带来的是并发设计模式实战系列,第十六章屏障(Barrier),废话不多说直接开始~

目录

一、核心原理深度拆解

1. 屏障的同步机制

2. 关键参数

二、生活化类比:团队登山

三、Java代码实现(生产级Demo)

1. 完整可运行代码

2. 关键方法说明

四、横向对比表格

1. 同步工具对比

2. 屏障参数配置对比

五、高级应用技巧

1. 多阶段任务控制

2. 动态线程管理

3. 性能监控

六、工程实践中的陷阱与解决方案

1. 死锁风险场景

2. 屏障断裂处理

七、性能优化技巧

1. 分层屏障设计

2. 与ForkJoinPool结合

八、分布式屏障扩展(ZooKeeper实现)

1. 核心原理

2. Java代码片段

九、监控与调试方案

1. 关键监控指标

2. Arthas诊断命令

十、与其他模式的组合应用

1. 屏障 + 生产者消费者模式

2. 代码示例


一、核心原理深度拆解

1. 屏障的同步机制

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  线程1       │    │  线程2       │    │  线程N       │
│ 执行阶段1    │    │ 执行阶段1    │    │ 执行阶段1    │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                  │                  │
       └─────────┬────────┴────────┬─────────┘
                 │   屏障点         │
                 ▼                  ▼
        ┌───────────────────┐
        │   所有线程到达后    │
        │   才继续执行阶段2   │
        └───────────────────┘
  • 协调机制:强制多个线程在某个点等待,直到所有参与线程都到达该点
  • 重置特性:CyclicBarrier 可重复使用(自动重置),CountDownLatch 不可重置

2. 关键参数

  • parties:需要等待的线程数量
  • barrierAction:所有线程到达后触发的回调(可选)

二、生活化类比:团队登山

系统组件

现实类比

核心行为

线程

登山队员

各自以不同速度攀登

屏障点

集合点

必须所有队员到齐才能继续前进

barrierAction

领队

检查装备、宣布下一阶段路线

  • 异常处理:若有队员受伤(线程中断),其他队员需要决定是否继续等待

三、Java代码实现(生产级Demo)

1. 完整可运行代码

import java.util.concurrent.*;
import java.util.Random;

public class BarrierPatternDemo {

    // 登山模拟
    static class MountainClimbing {
        private final CyclicBarrier barrier;
        private final Random rand = new Random();
        
        public MountainClimbing(int teamSize) {
            // 屏障点设置:队伍到齐后执行领队指令
            this.barrier = new CyclicBarrier(teamSize, () -> {
                System.out.println("\n=== 所有队员已到达集合点 ===");
                System.out.println("领队:检查装备完毕,向下一营地前进!");
            });
        }
        
        public void climb(String name) {
            try {
                // 第一阶段攀登
                int time = rand.nextInt(3000);
                System.out.printf("%s 正在攀登第一段(预计%dms)...\n", name, time);
                Thread.sleep(time);
                
                System.out.printf("[%s] 到达第一集合点,等待队友...\n", name);
                barrier.await();  // 等待所有队员
                
                // 第二阶段(屏障解除后)
                time = rand.nextInt(4000);
                System.out.printf("%s 向顶峰冲刺(预计%dms)...\n", name, time);
                Thread.sleep(time);
                System.out.printf("[%s] 成功登顶!\n", name);
                
            } catch (InterruptedException | BrokenBarrierException e) {
                System.out.printf("[%s] 登山中断: %s\n", name, e.getMessage());
            }
        }
    }

    public static void main(String[] args) {
        final int TEAM_SIZE = 3;
        MountainClimbing expedition = new MountainClimbing(TEAM_SIZE);
        
        // 创建登山线程
        ExecutorService pool = Executors.newFixedThreadPool(TEAM_SIZE);
        for (int i = 1; i <= TEAM_SIZE; i++) {
            String name = "队员-" + i;
            pool.execute(() -> expedition.climb(name));
        }
        
        pool.shutdown();
    }
}

2. 关键方法说明

// 1. 屏障等待(可设置超时)
barrier.await(5, TimeUnit.SECONDS);

// 2. 检查屏障状态
barrier.isBroken();  // 是否有线程被中断
barrier.getNumberWaiting();  // 当前等待的线程数

// 3. 重置屏障(CyclicBarrier特有)
barrier.reset();

四、横向对比表格

1. 同步工具对比

工具

可重用性

可中断

额外功能

适用场景

CyclicBarrier

支持回调(barrierAction)

多阶段任务同步

CountDownLatch

一次性

主线程等待多个子线程完成

Phaser

动态注册/注销

复杂分阶段任务

Exchanger

数据交换

线程间数据传递

2. 屏障参数配置对比

配置项

CyclicBarrier

CountDownLatch

初始化参数

等待线程数

需要countDown的次数

重用方式

自动重置

需重新创建实例

异常处理

BrokenBarrierException

无特殊异常


五、高级应用技巧

1. 多阶段任务控制

// 使用多个屏障实现多阶段同步
CyclicBarrier phase1 = new CyclicBarrier(3);
CyclicBarrier phase2 = new CyclicBarrier(3, ()->System.out.println("阶段2完成"));

// 线程中按顺序等待
phase1.await();
// 执行阶段1任务...
phase2.await();

2. 动态线程管理

// 使用Phaser替代(JDK7+)
Phaser phaser = new Phaser(1); // 注册主线程
for (int i = 0; i < 3; i++) {
    phaser.register(); // 动态注册任务线程
    new Thread(() -> {
        doWork();
        phaser.arriveAndDeregister(); // 完成任务后注销
    }).start();
}
phaser.arriveAndAwaitAdvance(); // 主线程等待

3. 性能监控

// 监控屏障等待情况
System.out.println("当前等待线程数: " + barrier.getNumberWaiting());
if (barrier.isBroken()) {
    System.out.println("警告:屏障已被破坏!");
}

六、工程实践中的陷阱与解决方案

1. 死锁风险场景

// 错误示例:线程池大小 < 屏障要求的parties数
ExecutorService pool = Executors.newFixedThreadPool(2);
CyclicBarrier barrier = new CyclicBarrier(3); // 要求3个线程
pool.submit(() -> barrier.await()); // 永远阻塞
pool.submit(() -> barrier.await());

解决方案

  • 确保线程池大小 ≥ parties数
  • 添加超时机制:
barrier.await(10, TimeUnit.SECONDS);

2. 屏障断裂处理

当某个等待线程被中断或超时,会触发BrokenBarrierException,此时需要:

try {
    barrier.await();
} catch (BrokenBarrierException e) {
    // 1. 记录断裂原因
    // 2. 重置屏障或终止任务
    barrier.reset(); // 仅CyclicBarrier有效
}

七、性能优化技巧

1. 分层屏障设计

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  子任务组1   │    │  子任务组2   │    │  子任务组N   │
│  (屏障A)     │    │  (屏障A)     │    │  (屏障A)     │
└──────┬──────┘    └──────┬──────┘    └──────┬──────┘
       │                  │                  │
       └─────────┬────────┴────────┬─────────┘
                 │   全局屏障B      │
                 ▼                  ▼
        ┌───────────────────┐
        │   最终聚合处理     │
        └───────────────────┘

适用场景:大数据分片处理(如MapReduce)

2. 与ForkJoinPool结合

ForkJoinPool pool = new ForkJoinPool(4);
CyclicBarrier barrier = new CyclicBarrier(4);

pool.execute(() -> {
    // 分治任务1
    barrier.await();
    // 合并结果...
});

八、分布式屏障扩展(ZooKeeper实现)

1. 核心原理

┌─────────────┐    ┌─────────────┐
│  节点1       │    │  节点2       │
│ 创建临时节点 │───>│ 监听节点变化 │
└─────────────┘    └─────────────┘
        │               ▲
        └───────┬───────┘
                ▼
        ┌─────────────┐
        │  ZooKeeper   │
        │  /barrier    │
        └─────────────┘

2. Java代码片段

public class DistributedBarrier {
    private final ZooKeeper zk;
    private final String barrierPath;
    
    public void await() throws Exception {
        zk.create(barrierPath + "/node", 
                 null, 
                 ZooDefs.Ids.OPEN_ACL_UNSAFE, 
                 CreateMode.EPHEMERAL_SEQUENTIAL);
        
        while (true) {
            List<String> nodes = zk.getChildren(barrierPath, false);
            if (nodes.size() >= REQUIRED_NODES) {
                break; // 所有节点就绪
            }
            Thread.sleep(100);
        }
    }
}

九、监控与调试方案

1. 关键监控指标

指标

采集方式

健康阈值

平均等待时间

Barrier日志打点 + Prometheus

< 任务超时时间的20%

屏障断裂次数

异常捕获统计

每小时 < 3次

线程阻塞比例

ThreadMXBean监控

< 线程数的30%

2. Arthas诊断命令

# 查看屏障状态
watch java.util.concurrent.CyclicBarrier getParties returnObj
# 监控等待线程
thread -b | grep 'await'

十、与其他模式的组合应用

1. 屏障 + 生产者消费者模式

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  生产者线程  │    │  生产者线程  │    │  屏障        │
│  生产数据    │───>│ 提交到队列   │───>│ 等待所有生产 │
└─────────────┘    └─────────────┘    └──────┬──────┘
                                              │
┌─────────────┐    ┌─────────────┐    ┌──────▼──────┐
│  消费者线程  │    │  消费者线程  │    │  屏障释放   │
│  开始消费    │<───│ 从队列获取   │<───│ 触发消费信号│
└─────────────┘    └─────────────┘    └─────────────┘

2. 代码示例

BlockingQueue<Data> queue = new LinkedBlockingQueue<>();
CyclicBarrier producerBarrier = new CyclicBarrier(3, () -> {
    System.out.println("所有生产者完成,启动消费者");
    startConsumers();
});

// 生产者线程
void produce() {
    queue.put(generateData());
    producerBarrier.await();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法探秘:和为K的子数组问题解析

算法探秘:和为K的子数组问题解析 一、引言 在算法的奇妙世界里,数组相关的问题总是层出不穷。“和为K的子数组”问题,看似简单,实则蕴含着丰富的算法思想和技巧。它要求我们在给定的整数数组中,找出和为特定值K的子数组个数。通过深入研究这个问题,我们不仅能提升对数组…

电力MOSFET的专用集成驱动电路IR2233

IR2233是IR2133/IR2233/IR2235 系列驱动芯片中的一种,是专为高电压、高速度的电力MOSFET和IGBT驱动而设计的。该系列驱动芯片内部集成了互相独立的三组板桥驱动电路,可对上下桥臂提供死区时间,特别适合于三相电源变换等方面的应用。其内部集成了独立的运算放大器可通过外部桥…

Qt 的原理及使用(1)——qt的背景及安装

1. Qt 背景介绍 1.1 什么是 Qt Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 。它为应⽤程序开发者提供了建⽴艺术级图形 界⾯所需的所有功能。它是完全⾯向对象的&#xff0c;很容易扩展。Qt 为开发者提供了⼀种基于组件的开发模 式&#xff0c;开发者可以通过简单的拖拽…

范式之殇-关系代数与参照完整性在 Web 后台的落寞

最近参加了一个PostgreSQL相关的茶会&#xff0c;感慨良多。原本话题是PostgreSQL 在 SELECT 场景中凭借其成熟的查询优化器、丰富的功能特性和灵活的执行策略&#xff0c;展现出显著优势。在窗口函数&#xff08;Window Functions&#xff09;、JOIN 优化、公共表表达式&#…

广西某建筑用花岗岩矿自动化监测

1. 项目简介 某矿业有限公司成立于2021年&#xff0c;是由某建筑材料有限公司与个人共同出资成立&#xff0c;矿区面积0.4069平方公里&#xff0c;可开采筑用花岗岩、建筑用砂岩。建筑用花岗岩、建筑用砂岩可利用资源量分别为6338.69万吨、303.39万吨&#xff0c;设计生产规模…

想更好应对突发网络与业务问题?需要一款“全流量”工具

目录 什么是“全流量”&#xff1f; 为什么“全流量”在突发问题中如此重要&#xff1f; 1. 抓住问题发生的“第一现场” 2. 绕开日志盲区 3. 精准应对安全威胁 实战场景下的“全流量”价值体现 实施“全流量”需要注意哪些点&#xff1f; 1. 数据量巨大&#xff0c;需…

C#里创建一个MaterialDesign3的导航条

本文里主要创建如下的窗口: 在这里就是实现左边的导航窗口的列表。 第一步先要定义下面的代码: <Window x:Class="MDIXWindow.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microso…

Oracle OCP认证考试考点详解083系列09

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 41. 第41题&#xff1a; 题目 解析及答案&#xff1a; 关于应用程序容器&#xff0c;以下哪三项是正确的&#xff1f; A) 它可以包含单个…

如何进行室内VR全景拍摄?

如何进行室内VR全景拍摄&#xff1f; 室内VR全景拍摄作为先进的视觉技术&#xff0c;能够为用户提供沉浸式的空间体验。本文介绍如何进行室内VR全景拍摄&#xff0c;并阐述众趣科技在这一领域的技术支持和服务优势。 室内VR全景拍摄基础 1. 室内VR全景拍摄概述 室内VR全景拍…

C# 综合示例 库存管理系统20 操作员管理(FormAdmin)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 图99A-35 操作员管理窗口设计 增加操作员或者重置密码&#xff0c;密码都设置为默认的“123456”&#xff0c;操作员可以登录系统后再修…

[JAVAEE]HTTP协议(2.0)

响应报文格式 响应报文格式由首行&#xff0c;响应头&#xff08;header&#xff09;&#xff0c;空行&#xff0c;正文&#xff08;body&#xff09; 组成 响应报文首行包括 1.版本号 如HTTP/1.1 2.状态码(如200) 描述了请求的结果 3.状态码描述(如OK) 首行——状态码…

VUE+ElementUI 使用el-input类型type=“number” 时,取消右边的上下箭头

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在项目中有时候需要输入框的type“number”&#xff0c;这个时候&#xff0c;输入框的右边就会出现两个按钮&#xff0c;这两个按钮可以递增/递减&#xff0c;但是这样输入框看上去就不太美观&#x…

计算机视觉——MedSAM2医学影像一键实现3D与视频分割的高效解决方案

引言 在乡村医院的傍晚高峰时段&#xff0c;扫描室内传来阵阵低沉的嗡鸣声&#xff0c;仿佛一台老旧冰箱的运转声。一位疲惫的医生正全神贯注地检查着当天的最后一位患者——一位不幸从拖拉机上摔下的农民&#xff0c;此刻正呼吸急促。CT 机器飞速旋转&#xff0c;生成了超过一…

垃圾分类宣教小程序源码介绍

随着环保意识的提升&#xff0c;垃圾分类已成为我们生活中不可或缺的一部分。为了更好地宣传和教育大众关于垃圾分类的知识&#xff0c;一款基于ThinkPHP、FastAdmin和UniApp开发的垃圾分类宣教小程序应运而生。 该小程序源码结合了ThinkPHP的强大后台功能、FastAdmin的高效管…

【wpf】12 在WPF中实现HTTP通信:封装HttpClient的最佳实践

一、背景介绍 在现代桌面应用开发中&#xff0c;网络通信是不可或缺的能力。WPF作为.NET平台下的桌面开发框架&#xff0c;可通过HttpClient轻松实现与后端API的交互。本文将以一个实际的HttpsMessages工具类为例&#xff0c;讲解如何在WPF中安全高效地封装HTTP通信模块。 二、…

【Hive入门】Hive安全管理与权限控制:用户认证与权限管理深度解析

目录 引言 1 Hive安全管理体系概述 2 Hive用户认证机制 2.1 Kerberos集成认证 2.1.1 Kerberos基本原理 2.1.2 Hive集成Kerberos配置步骤 2.1.3 Kerberos认证常见问题排查 2.2 LDAP用户同步 2.2.1 LDAP协议概述 2.2.2 Hive集成LDAP配置 2.2.3 LDAP与Hive用户同步架构…

解决 Builroot 系统编译 perl 编译报错问题

本文提供一种修复 Builroot 系统编译 perl 编译报错途径 2025-05-04T22:45:08 rm -f pod/perl5261delta.pod 2025-05-04T22:45:08 /usr/bin/ln -s perldelta.pod pod/perl5261delta.pod 2025-05-04T22:45:08 /usr/bin/gcc -c -DPERL_CORE -fwrapv -fpcc-struct-return -pipe -f…

强化学习PPO算法学习记录

1. 四个模型&#xff1a; Policy Model&#xff1a;我们想要训练的目标语言模型。我们一般用SFT阶段产出的SFT模型来对它做初始化。Reference Model&#xff1a;一般也用SFT阶段得到的SFT模型做初始化&#xff0c;在训练过程中&#xff0c;它的参数是冻结的。Ref模型的主要作用…

从零开始:用PyTorch构建CIFAR-10图像分类模型达到接近1的准确率

为了增强代码可读性&#xff0c;代码均使用Chatgpt给每一行代码都加入了注释&#xff0c;方便大家在本文代码的基础上进行改进优化。 本文是搭建了一个稍微优化了一下的模型&#xff0c;训练200个epoch&#xff0c;准确率达到了99.74%&#xff0c;简单完成了一下CIFAR-10数据集…

初学Python爬虫

文章目录 前言一、 爬虫的初识1.1 什么是爬虫1.2 爬虫的核心1.3 爬虫的用途1.4 爬虫分类1.5 爬虫带来的风险1.6. 反爬手段1.7 爬虫网络请求1.8 爬虫基本流程 二、urllib库初识2.1 http和https协议2.2 编码解码的使用2.3 urllib的基本使用2.4 一个类型六个方法2.5 下载网页数据2…