天增的博客
首页
博客
  • 分布式解决方案
  • Java并发工具包
  • redis
  • LeetCode
  • 系统设计
  • JVM体系
Github (opens new window)
Rss (opens new window)
  • zh-CN
  • en-US
首页
博客
  • 分布式解决方案
  • Java并发工具包
  • redis
  • LeetCode
  • 系统设计
  • JVM体系
Github (opens new window)
Rss (opens new window)
  • zh-CN
  • en-US
  • Java并发工具包
  • 并发基础
    • 线程基础
      • Thread的状态
      • 进程与线程
      • 正确停止线程的方式
      • Thread的实现方式
      • waitnotifynotifyAll
      • 生产者消费者模型
    • 线程安全
      • 线程不安全
      • 线程安全
      • 需要注意线程安全问题的情况
  • 并发工具
    • 线程协作
      • Semaphore信号量
      • CountDownLatch详解
      • 使用CompletableFuture解决旅游平台问题
      • 使用CyclicBarrier解决团建问题
        • 团建问题介绍
        • 模拟场景
        • CyclicBarrier 和 CountDownLatch 的异同
    • Future
      • Future主要功能
      • FutureTask源码分析
    • ThreadLocal
      • ThreadLocal内存泄漏
      • ThreadLocal使用场景
    • 原子类
      • 原子类的作用概览
      • 原子类的性能分析
    • 阻塞队列
      • 常见的阻塞队列
      • 阻塞队列的常用方法
      • 什么是阻塞队列
    • 并发容器
      • HashMap
      • CopyOnWriteArrayList
      • ConcurrentHashMap详解
    • 线程池
      • 为什么多线程会带来性能问题
      • 线程池的优势
      • 创建线程池的参数
        • 如何设置线程数
      • 线程池线程复用原理
      • ForkJoin框架
    • 各种锁
      • 锁的种类和特点
        • 公平锁非公平锁
        • 自旋锁非自旋锁
        • 共享锁独占锁
        • 乐观锁和悲观锁
      • JVM锁优化
      • synchronized和Lock的对比
      • lock的常用方法
  • 底层原理
    • CAS原理
    • AQS框架
    • 伪共享
    • java内存模型
      • Java内存模型介绍
      • happens-before规则
  • topic
  • Java并发工具包
  • 并发工具
  • 线程协作
  • 使用CyclicBarrier解决团建问题
2022-04-21
目录

使用CyclicBarrier解决团建问题

# 使用CyclicBarrier解决团建问题

# 团建问题介绍

假设有一家公司要全体员工进行团建活动,活动内容为爬山,但是由于每一个人爬山的时间都是不一样的,因此需要等到所有人都爬过山头之后才能够一起去吃饭,但是每个饭桌只能容纳2个人。

# 模拟场景

我们用代码模拟这个场景:

public class PartyBuilding {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> System.out.println("有两人到齐了,干饭~~~"));
        Climbing employee1 = new Climbing("甲", cyclicBarrier);
        Climbing employee2 = new Climbing("乙", cyclicBarrier);
        Climbing employee3 = new Climbing("丙", cyclicBarrier);
        Climbing employee4 = new Climbing("丁", cyclicBarrier);
        Climbing employee5 = new Climbing("戊", cyclicBarrier);
        Climbing employee6 = new Climbing("己", cyclicBarrier);
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        executorService.submit(employee1);
        executorService.submit(employee2);
        executorService.submit(employee3);
        executorService.submit(employee4);
        executorService.submit(employee5);
        executorService.submit(employee6);
    }

    public static class Climbing implements Runnable {
        private String name;
        private CyclicBarrier cyclicBarrier;

        public Climbing(String name, CyclicBarrier cyclicBarrier) {
            this.name = name;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println("员工:" + name + "开始爬山~~");
            try {
                long climbingTime = (long) (Math.random() * 4000);
                Thread.sleep(climbingTime);
                System.out.println("员工:" + name + " 用时:" + climbingTime + ",等待人齐去吃饭~~");
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

员工:乙开始爬山~~
员工:戊开始爬山~~
员工:甲开始爬山~~
员工:丁开始爬山~~
员工:丙开始爬山~~
员工:丁 用时:813,等待人齐去吃饭~~
员工:丙 用时:2022,等待人齐去吃饭~~
有两人到齐了,干饭~~~
员工:己开始爬山~~
员工:乙 用时:2500,等待人齐去吃饭~~
员工:己 用时:933,等待人齐去吃饭~~
有两人到齐了,干饭~~~
员工:甲 用时:3215,等待人齐去吃饭~~
员工:戊 用时:3898,等待人齐去吃饭~~
有两人到齐了,干饭~~~

能够看到,这段代码输出的结果,符合我们的预期

从这段代码中,首先建了参数为2的一个CyclicBarrier,这意味着需要等待2个线程到达这个集结点才统一放行,每2个执行一次runable里面的干饭逻辑。

# CyclicBarrier 和 CountDownLatch 的异同

# 相同点

都能够阻塞一个或一组线程,直到某个预设的条件达成发送,再统一出发。

# 不同点

# 作用对象不同

CyclicBarrier作用于线程,需要等到线程执行完成之后,计数器则减一,到0的时候就继续执行。

CountDownLatch作用于事件,需要通过调用countDown才能够计数器减一,直到0才继续执行。

# 可重用性不同

CyclicBarrier可以重复使用,在计时器归零后,会重置计时器重新开始计数,甚至还能通过reset主动重置计数器,如果重置时有线程已经调用await并开始等待,等待的线程会抛出BrokenBarrierException异常。

CountDownLatch在倒数到0的时候,就不能再次使用了,除非新建一个新的实例。

# 执行动作不同

CyclicBarrier有执行动作,在满足计数器归零的时候会调用barrierAction执行一个回调操作。

CountDownLatch没有这个功能

最近更新
01
以 root 身份启动 transmission-daemon
12-13
02
Debian系统安装qbittorrent-nox
12-09
03
LXC Debain12安装zerotier并实现局域网自动nat转发
07-29
更多文章>
Theme by Vdoing | Copyright © 2015-2024 天增 | 苏ICP备16037388号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式