【JUC的四大同步辅助类】

文章目录

  • 一、CountDownLatch
  • 二、CyclicBarrier
  • 三、Semaphore
  • 四、Phaser


提示:以下是本篇文章正文内容,下面案例可供参考

一、CountDownLatch

CountDownLatch如同火箭发射,计数只能不断减减,当到达0时即发射
场景示例:考场中有多个同学考试,每个同学写完试卷后,将试卷交给老师即可离开,老师需要收齐所有人的试卷后才能离开。

代码如下(示例)

public class Test {
    public static void main(String[] args) throws InterruptedException {
        // CountDownLatch 倒计时到0,发射(减法)

        // 考场学生人数为 6(一旦定下就不能在增加)
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    // 模拟每个学生完成试卷的时间不同(线程休眠随机时间)
                    Thread.sleep(new Random().nextInt(3000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t同学写完,离开教室");
                // 上交试卷给老师(走一个,计数减少一个)
                countDownLatch.countDown();
            }, i + "号考生").start();
        }

        // 主线程相当于老师,需要等所有的人交卷,才能离开(阻塞当前线程,等待所有线程完成任务,即 countDown)
        countDownLatch.await();

        Thread.currentThread().setName("老师");
        System.out.println(Thread.currentThread().getName() + "\t收齐试卷,关门走人");
    }
}

输出结果

在这里插入图片描述


二、CyclicBarrier

CyclicBarrier如同游戏匹配,不凑齐人数,就一直在匹配界面,达到指定人数后才能开始对战

代码如下(示例)

public class Test {
    public static void main(String[] args) throws InterruptedException {
        // CyclicBarrier 指定值达到 0,发射

        // 需要十个人才能开始游戏,(指定个数,之后不能改变,满足条件后,自动执行 Runnable 方法)
        CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> {
            System.out.println("十个人已经全部确认,开始游戏");
        });

        for (int i = 1; i <= 10; i++) {
            final int tmpInt = i;
            new Thread(() -> {
                try {
                    // 模拟玩家匹配时间
                    Thread.sleep(new Random().nextInt(3000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "\t已经确认");
                try {
                    // 等待其他玩家准备(阻塞等待,等待人数减 1,减到 0,就发车)
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, tmpInt + "号玩家").start();
        }

    }
}

输出结果
在这里插入图片描述


三、Semaphore

Semaphore如同一个停车场,里面的车位数是固定的,当停满车后,必须有车出来才能再进

Semaphore 主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。
涉及到并发就有有两种模式:

  1. 非公平(谁抢到是谁的),默认是非公平的
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }
  1. 公平(先来后到),当 fair 为 true 是公平的
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

代码如下(示例)

public class Test {
    public static void main(String[] args) throws InterruptedException {
        // 一共 3 个停车位(资源数开始时固定)
        Semaphore semaphore = new Semaphore(3);// 默认非公平(抢占式)

        // 模拟 6 辆汽车要停车
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    // 询问还有没有停车位,有就进去,没有等待(获得资源)
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "\t抢到车位");
                    // 模拟停车时间
                    Thread.sleep(new Random().nextInt(3000));
                    System.out.println(Thread.currentThread().getName() + "\t事情办完,离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 办完事情,开车离开(释放资源)
                    semaphore.release();
                }
            }, i + "号车主").start();
        }
    }
}

输出结果
在这里插入图片描述


四、Phaser

Phaser是JDK 7新增的一个同步辅助类,它可以实现CyclicBarrier和CountDownLatch类似的功能,而且它支持对任务的动态调整,并支持分层结构来达到更高的吞吐量。

CountDownLatch 和 CyclicBarrier 在最初就固定了线程的数量,而且中途不可改变,当完成指定的任务后,就不能再次使用,Phaser 就解决了该问题。

class player implements Runnable {

    private final Phaser phaser;

    player(Phaser phaser) {
        this.phaser = phaser;
    }

    @Override
    public void run() {
        try {
            // 第一阶段——确定参赛的运动员人数(等待创建好所有线程再开始)
            phaser.arriveAndAwaitAdvance();

            // 第二阶段——等待所有选手都做好准备,发令枪再开始
            Thread.sleep(new Random().nextInt(3000));// 模拟热身准备
            System.out.println(Thread.currentThread().getName() + "号运动员准备完毕");
            phaser.arriveAndAwaitAdvance();

            // 第三阶段——所有运动员开始跑步
            Thread.sleep(new Random().nextInt(3000));// 模拟跑步时间
            System.out.println(Thread.currentThread().getName() + "号运动员冲线!");

            // 冲线后结束(线程下线注销)
            phaser.arriveAndDeregister();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {

        // 模拟了 100 米赛跑,10 名运动员,只等裁判一声令下。当所有人都到达终点时,比赛结束。
        // 设置初始的注册人数(1 个裁判)
        final Phaser phaser = new Phaser(1);
        // 十名运动员
        for (int index = 0; index < 10; index++) {
            // 每个运动员都注册到其中,即确定参加比赛(动态增加,复用)
            phaser.register();
            new Thread(new player(phaser), index + "号运动员").start();
        }
        System.out.println("比赛开始");
        // 裁判下线,注销当前线程,比赛开始
        phaser.arriveAndDeregister();
        // 所有运动员是否到达终点,没有就一直等待
        while (!phaser.isTerminated()) {
        }
        System.out.println("所有运动员到达终点,比赛结束");

    }
}

输出结果
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

elect函数可以设置等待时间,

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;贝叶斯滤波与Kalman估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能&#xff0c…

ssm基于BS的仓库在线管理系统的设计与实现论文

摘 要 如今的时代&#xff0c;是有史以来最好的时代&#xff0c;随着计算机的发展到现在的移动终端的发展&#xff0c;国内目前信息技术已经在世界上遥遥领先&#xff0c;让人们感觉到处于信息大爆炸的社会。信息时代的信息处理肯定不能用之前的手工处理这样的解决方法&#x…

OpenCV-Python(23):傅里叶变换

原理 傅里叶变换是一种数学变换&#xff0c;用于将一个函数&#xff08;在图像处理中通常是图像&#xff09;从时域&#xff08;空域&#xff09;转换到频域。它将函数表示为一系列正弦和余弦函数的和&#xff0c;用于分析信号的频率和相位信息。 傅里叶变换的原理是将一个连续…

【iOS安全】JS 调用Objective-C中WKWebview Handler的三种方式

有三种实现途径 1. WKScriptMessageHandler OC部分&#xff1a;注册并实现Handler 将OC中的方法"nativeMethod"注册为JavaScript Message Handler&#xff0c;从而WebView中的JavaScript代码可以调用该方法 // Register in Objective-C code - (void)setupWKWebVi…

No Magic—复杂机电产品系统架构开发套件

产品概述 CATIA Magic&#xff0c;原名MagicDraw&#xff0c;俗称No Magic&#xff0c;被达索收购后融入3DExperience产品协同研发管理平台中&#xff0c;形成更具协同体验的系统工程解决方案。该软件提供对SysML/UML/UAF语言的完整支持&#xff0c;提供独有的MagicGrid方法论&…

5分钟了解接口测试

接口测试是指对系统接口进行测试的一种质量保障手段&#xff0c;主要是验证接口的功能、性能、安全性等方面是否符合预期。 在接口测试中&#xff0c;可以测试以下内容&#xff1a; 功能测试&#xff1a;验证接口的输入和输出是否符合预期&#xff0c;包括参数的正确性、返回结…

【无标题】idea的lombok插件支持@SuperBuilder注解啦

在我的博客阅读本文 1. 前言 今早进公司打开idea&#xff0c;弹出更新提示&#xff0c;简单看了下&#xff0c;原来是idea的lombok插件更新了&#xff0c;惊喜的发现update log上写着Add support for SuperBuilder。 为什么说是惊喜呢&#xff1f;因为之前也有用到这个的场景…

Go后端开发 -- Go Modules

Go后端开发 – Go Modules 文章目录 Go后端开发 -- Go Modules一、什么是Go Modules?二、GOPATH的工作模式1.GOPATH模式2.GOPATH模式的弊端 三、Go Modules模式创建项目1.go mod命令2.go mod环境变量3.使用Go Modules初始化项目4.修改模块的版本依赖关系 四、Go Modules下impo…

数据库:基础SQL知识+SQL实验2

&#xff08;1&#xff09;基础知识&#xff1a; 1.JOIN&#xff08;连接&#xff09;&#xff1a; 连接操作用于根据指定的条件将两个或多个表中的数据行合并在一起。JOIN 可以根据不同的条件和方式执行&#xff0c;包括等值连接、不等值连接等。 &#xff08;1&#xff09…

SAP BAPI 客户主数据创建:cmd_ei_api=>maintain_bapi

BAPI函数&#xff1a;cmd_ei_api>maintain_bapi 事物代码&#xff1a;XD01/XD02 客户主数据创建、修改、拓展功能开发 数据结构定义&#xff1a; 基本视图信息 公司代码信息结构&#xff1a; 销售视图信息结构: 客户主数据税分类信息结构&#xff1a; 代码参考 详细代码…

C++面向对象编程与泛型编程(GP)

C既支持面向对象编程&#xff0c;又支持泛型编程 1.面向对象编程 将数据结构与处理方法&#xff08;容器与算法&#xff09;组成对象封装在一个类中&#xff0c;通过类的封装隐藏内部细节&#xff0c;可以使用继承&#xff0c;多态等方法。 注意&#xff1a;list容器本身带有…

计算机毕业设计——SpringBoot 招投标 任务发布网站(附源码)

1&#xff0c;绪论 在市场范围内&#xff0c;任务发布网站很受欢迎&#xff0c;有很多开发者以及其他领域的牛人&#xff0c;更倾向于选择工作时间、工作场景更自由的零工市场寻求零散单子来补贴家用。 如今市场上&#xff0c;任务发布网站鱼龙混杂&#xff0c;用户需要找一个…

CH341StreamI2C参数解释

总体思路&#xff1a; 第一步&#xff1a;使用EEPROM写入相应的数据 第二步&#xff1a;使用EEPROM读取相应的数据 第三步&#xff1a;使用CH341StreamI2C函数还原读取过程 每一步需要逻辑分析仪进行对比。 第一步&#xff1a;数据写入CH341WriteEEPROM 使用CH341WriteE…

性能测试之Mysql数据库调优

一、前言 性能调优前提&#xff1a;无监控不调优&#xff0c;对于mysql性能的监控前几天有文章提到过&#xff0c;有兴趣的朋友可以去看一下 二、Mysql性能指标及问题分析和定位 1、我们在监控图表中关注的性能指标大概有这么几个&#xff1a;CPU、内存、连接数、io读写时间…

【网络安全】【密码学】常见数据加(解)密算法及Python实现(一)

一、Base64编码 1、算法简介 Base64是一种常见的编&#xff08;解&#xff09;码方法&#xff0c;用于传输少量二进制数据。该编码方式较为简短&#xff0c;并不具有可读性&#xff0c;对敏感数据可以起到较好的保护作用。 2、Python实现&#xff08;调库&#xff09; &…

每日一道算法题day-one(备战蓝桥杯)

从今天开始博主会每天做一道算法题备战蓝桥杯&#xff0c;并分享博主做题的思路&#xff0c;有兴趣就加入我把&#xff01; 算法题目&#xff1a; 有一个长度为 N 的字符串 S &#xff0c;其中的每个字符要么是 B&#xff0c;要么是 E。 我们规定 S 的价值等于其中包含的子…

C++模板(泛型)

1. 模板 1.1 知识点 模板&#xff1a;template 泛型编程&#xff1a; 是指数据的类型是广泛&#xff0c;任意的数据类型 模板&#xff1a;可以将一个函数或类描述成一个模板&#xff0c;例如&#xff1a;画画&#xff0c;给一个人物模型上色彩&#xff0c;根据用户上的色彩是什…

Bean如何诞生与消亡:生命周期探秘【beans 二】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Bean如何诞生与消亡&#xff1a;生命周期探秘【beans 二】 前言bean的创建过程bean的初始化阶段1. 实现InitializingBean接口&#xff1a;2. 使用PostConstruct注解&#xff1a; bean的属性注入1. Set…

视频倒放软件,看视频如何演绎“逆袭”之旅

你是否厌倦了日复一日的平淡生活&#xff0c;渴望时光倒流&#xff0c;重温那些逝去的精彩瞬间&#xff1f;在数字技术的世界里&#xff0c;这样的愿望或许不再遥不可及。视频倒放仿佛让时光倒流&#xff0c;给我们的视觉带来了全新的冲击&#xff0c;今天&#xff0c;让我们一…

新手第一次在linux上用git上传代码到仓库全过程

目录 背景&#xff1a; 过程&#xff1a; -1.去github.com自己的账号先建个仓库repository 0.命令行输入 git version 看下有无安装git 1.git init 初始化了一个Git仓库&#xff0c;你可以 ls -a 看见这个隐藏的目录 3.git add . 添加要上传的文件到Git的暂存区&#xff0…