知行合一
Github
顺翔的技术驿站
顺翔的技术驿站
  • README
  • ABOUTME
  • Computer Science
    • 数据结构与算法
      • 位运算以及位图
      • 随机数
      • 递归
      • 经典排序算法
      • 经典查找算法
      • 数组和动态数组
      • 链表
      • 栈和队列
      • 树
      • 哈希表
    • 计算机网络
      • 物理层
      • 数据链路层
      • 网络层
        • TCP
      • 运输层
      • 应用层
      • HTTP
        • HTTPS的原理
        • DNS详解
        • file协议
        • 邮件协议
    • 设计模式
      • 单例模式
      • 建造者模式
      • 原型模式
      • 工厂模式
      • 享元模式
      • 代理模式
      • 装饰者模式
      • 桥接模式
      • 适配器模式
      • 外观模式
      • 组合模式
      • 事件驱动
      • 有限状态机
      • 备忘录模式
      • 模板方法模式
      • 策略模式
      • 迭代器模式
      • 命令模式
      • 解释器模式
    • 加密与解密
      • 数字证书原理
      • cfssl
  • Programming Language
    • 编程语言学习要素
    • Java
      • 集合
        • List
          • ArrayList
          • Vector
          • Stack
          • LinkedList
        • Iterator
        • Set
          • HashSet
          • TreeSet
        • Map
          • HashMap
          • HashTable
          • TreeMap
          • LinkedHashMap
      • 常用API
        • 日期时间处理
        • System
        • Random
        • Arrays
        • Scanner
        • 格式化输出
      • java特性
        • java5特性
        • java8特性
        • java9特性
        • java10特性
        • java11特性
      • 并发编程
        • 线程基础
        • 线程同步:synchronized及其原理
        • 线程同步: volatile
        • 锁机制
        • 锁的分类与对应的Java实现
        • JUC:同步辅助类
        • JUC: AtomicXXX
        • 线程池
        • ThreadLocal详解
      • 测试
        • 使用JMH进行基准测试
      • JVM
        • 强引用、软引用、弱引用、虚引用
        • jvm内存模型
        • jvm优化
        • GC算法与回收器
        • 静态绑定与动态绑定
      • ORM
        • Mybatis
          • IBatis常用操作
      • Web编程
        • Servlet详解(一)
        • Servlet详解(二):request和response对象
        • Servlet详解(三):会话技术与Cookie
        • JSP详解(一):页面构成、EL表达式
        • JSP详解(二):九大内置对象
        • JavaWeb的编码问题
        • Thymeleaf
      • Velocity
      • Java日志框架总结
      • Spring
        • SpringIOC
        • SpringMVC
        • SpringBoot源码
      • 其他
        • Apache Commons Lang使用总结
        • 使用FtpClient进行ftp操作
        • Java PDF操作总结
        • Java使用zip4j进行文件压缩
        • Java解析Excel总结
    • JVM Language
      • Groovy
      • Scala
    • Kotlin
      • 变量和常量
      • 数据类型
        • 基本数据类型
        • 容器类型
        • 函数类型
        • null和null安全
      • 流程控制
      • 包
      • 面向对象
    • Golang
      • 关键字与标识符
      • 变量和常量
      • 数据类型
      • 函数
      • 常用API
        • 时间日期处理
        • 字符串操作
        • 正则表达式
      • 控制语句
      • 包package
      • 面向对象
      • 错误处理
      • 命令行编程
        • Cobra
      • 文件操作
      • 测试
      • 并发编程
        • sync包详解
      • 数据格式与编码
        • 使用encoding包操作xml
        • 使用encoding包操作json
        • 使用magiconair操作properties
        • 使用go-ini操作ini
      • 反射
      • Build Tools
        • Go Module
        • Go Vendor
      • 日志框架
        • zap日志框架
      • Web编程
        • Gin
    • JavaScript
      • 数据类型
      • ECMAScript
        • ECMAScript6
      • NodeJS
    • TypeScript
      • 变量和常量
      • 数据类型
      • 函数
      • 面向对象
      • 泛型
      • Build Tools
        • tsc编译
        • 与webpack整合
    • Python
      • BuildTools
        • requirements.txt
        • Ananconda
    • Swift
      • 变量和常量
    • Script Language
      • Regex
      • BAT
      • Shell
    • Markup Language
      • Markdown
      • Yaml
  • Build Tools
    • CMake
    • Maven
      • 搭建Nexus私服
      • maven使用场景
    • Gradle
  • Version Control
    • Git
      • Git工作流
      • Git分支管理
      • Git Stash
      • Git Commit Message规范
      • .gitttributes文件
    • SVN
  • Distributed
    • 分布式基础理论
      • 互联网架构演变
      • 架构设计思想AKF拆分原则
      • CAP理论
      • BASE理论
    • 一致性
      • 一致性模型
      • 共识算法
        • Paxos
        • Raft
        • ZAB
      • 复制
        • 主从复制
        • Quorum机制
        • Nacos Distro协议
      • 缓存一致性
        • 双写一致性
        • 多级缓存一致性
    • 事务一致性
      • Seata
      • 本地消息表实现方案
      • 关于dpad的事务问题的分析
    • IO
    • RPC协议
    • 序列化
    • Session共享
    • 分布式协调
      • Zookeeper
        • zk集群4节点搭建
    • 服务治理
      • Dubbo分布式治理
    • 分布式ID
      • 分布式ID生成策略总结
    • 分布式锁
    • 应用服务器
      • Tomcat
    • Web服务器
      • Nginx
        • Nginx的基本配置
        • ab接口压力测试工具
        • nginx模块
        • 随机访问页面
        • 替换响应内容
        • 请求限制
        • 访问控制
        • 状态监测
        • nginx应用场景
        • 代理服务
        • 负载均衡
        • 缓存
        • 静态资源服务器和动静分离
        • 附录
      • Kong
    • 缓存中间件
      • Caffeine
      • memcached
      • Redis
        • Centos下安装Redis
        • RatHat下安装Redis
    • 数据库中间件
      • ShardingSphere
      • MyCat2
    • 消息中间件
      • Kafka
      • RocketMQ
  • Microservices
    • 服务发现
      • Nacos注册中心
      • Consul
    • 配置中心
      • Apollo
    • 消息总线
    • 客户端负载均衡
    • 熔断器
    • 服务网关
    • 链路追踪
      • Skywalking
  • Domain-Specific
    • Auth
      • 有关权限设计的思考
      • 认证方式
      • JWT
    • 任务调度
      • QuartzScheduler
      • Elastic-Job
      • XXL-Job
      • PowerJob
    • 工作流
      • BPM
      • Activiti
      • Flowable
    • 规则引擎
      • Drools
  • Architect
    • DDD领域驱动设计
      • 三层架构设计
      • 四层架构设计
    • Cola
    • 代码设计与代码重构
      • 重构改变既有代码设计
      • 枚举规范化
      • 接口幂等
      • 限流
      • 历史与版本
      • 逻辑删除和唯一索引
      • 业务对象设计
    • 单元测试
      • SpringBoot单元测试实践
    • 项目管理
    • APM
      • SkyWalking
      • Arthas
    • 性能优化
      • 接口性能优化
    • 系统设计
      • 流程中台
      • 短信中台
      • 权限中台
        • 智电运维平台组织架构改造二期
  • Database
    • Oracle
      • Docker下安装oracle11g
    • IBM DB2
    • Mysql
      • 安装Mysql
      • 用户与权限管理
      • MySQL的逻辑架构
      • 存储引擎
      • 索引详解
      • MySql的列类型
      • MySql中表和列的设计
      • MySql的SQL详解
      • 锁机制
      • 事务
      • Mysql函数总结
      • MySql存储过程详解
      • MySql触发器详解
      • Mysql视图详解
      • Mysql中Sql语句的执行顺序
      • 配置MySql主从和读写分离
      • MySql的备份策略
      • MySql分库分表解决方案
      • MySql优化总结
      • MySQL实战调优
        • schema与数据类型优化
    • Mongo
  • File System
    • README
    • HDFS
    • FastDFS
    • MinIO
  • Linux
    • 常用的Linux命令
    • vim
    • Linux磁盘管理
    • Linux系统编程
    • RedHat
      • rpm包管理器具体用法
    • Ubuntu
      • Ubuntu下录制屏幕并做成gif图片
      • Ubuntu20.05LiveServe版安装
  • DevOps
    • VM
      • 新建一个新的Linux虚拟机需要配置的东西
      • VMware桥接模式配置centos
      • VMwareFusion配置Nat静态IP
    • Ansible
    • Container
      • Docker
        • Dockerfile详解
        • DockerCompose详解
      • Containerd
    • Kubernetes
      • 安装k8s
        • 使用Minikube安装k8s
        • centos7.x下使用kubeadm安装k8s1.21
        • ubuntu20下使用kubeadm安装k8s1.21
        • centos7.x下使用二进制方式安装k8s1.20
        • 使用DockerDesktop安装K8s(适用M1芯片)
      • 切换容器引擎
      • 使用k8s部署项目的流程
      • 集群维护-备份升级排错
    • Gitlab
      • GitlabCI/CD
    • CI/CD
      • ArgoCD
  • Big-Data
    • Hadoop
    • MapReduce
    • HDFS
  • Front-End
    • Android
      • Log的使用、自定义Log工具类
      • Android倒计时功能实现
      • 解决ViewDrawableLeft左侧图片大小不可控的问题
      • AndroidSQLite基本用法
      • View的生命周期
      • 工具类
      • WebView详解
      • ViewTreeObserver类监听ViewTree
      • 在onCreate中获取控件的宽高等信息的几种方法
      • View的foreground属性
        • MaterialDesign
          • BottomNavigationBar
          • CardView
          • Elevation高度、shadows阴影、clipping裁剪、tint着色
          • TouchFeedbackRipple波纹动画
      • Volley完全解析——使用、源码
      • Android围住神经猫的实现
      • LookLook剖析,架构概述——MVP、Retrofit+RxJava
      • Android性能优化之渲染
    • Browser
      • 浏览器的工作原理
    • HTML
      • DOCTYPE标签、XHTML与HTML的区别
    • CSS
      • CSS的继承性、层叠性、权重
      • CSS浮动float详解(一):标准文档流
      • CSS浮动float详解(二):使用float
      • CSS浮动float详解(三):清除浮动方案
    • Tools Lib
      • JavaScript 文件下载解决方案-download.js
      • js-url 用于url的js开源库
      • jsuri 用于操作url的js开源库
      • window offset
    • React
      • 模块化和组件
      • 组件的三大核心属性
      • 事件处理
      • 表单数据收集
      • 生命周期
      • DOM的diff算法
      • 工程化
        • 脚手架create-react-app
        • 工程结构和模块化
      • 路由
  • Design
    • 产品设计
      • 交互设计
由 GitBook 提供支持
在本页
  • CountDownLatch
  • CyclicBarrier
  • Phaser
  • Semaphore
  • Exchanger
  • LockSupport

这有帮助吗?

在GitHub上编辑
  1. Programming Language
  2. Java
  3. 并发编程

JUC:同步辅助类

java.util.concurrent 包下,有一些关于同步的辅助工具类,比如CountDownLatch、CyclicBarrier等。

CountDownLatch

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。CountDownLatch允许创建时传入一个初始值,代表门闩的数量,cdl调用await方法进行阻塞;cdl通过 countDown() 方法拿掉一个门闩,直到门闩的数量变为0时,await阻塞结束。

public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch cdl = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    Thread.sleep(finalI * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行完毕");
                cdl.countDown();
            }, "线程" + i).start();
        }
        cdl.await();
        System.out.println("所有门闩已经打开,继续执行main线程!");
    }

}

CyclicBarrier

Cyclic 循环的,Barrier 栅栏,屏障。类似满人发车,每凑满20人,才会继续执行,下面是使用示例:

public class CyclicBarrierDemo {

    public static void main(String[] args) {
        // runnable 是可选参数,代表达到数量后要执行的代码
        CyclicBarrier cyclicBarrier = new CyclicBarrier(20, new Runnable() {
            @Override
            public void run() {
                System.out.println("已经20个人了,发车!");
            }
        });
        for (int i = 0; i < 100; i++) {
            int finalI = i;
            new Thread(() -> {
                System.out.println("i:" + finalI);
                try {
                    cyclicBarrier.await(); // 等待发车,当满20个才会继续执行
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                // 其他业务逻辑
            }, "线程" + i).start();
        }
    }
}

CyclicBarrer 应用于多个线程并发执行,比如网络操作、文件操作同时执行;当所有线程都准备完毕,下面的操作才可进行。

Phaser

阶段执行,jdk7引入。多个线程执行一个任务,此任务分为多个阶段,每个阶段要求全部或者部分线程并发执行并且所有目标线程执行完毕后才可继续执行下一阶段的场景。比如达尔文遗传算法。下面使用Phaser对结婚场景进行模拟,结婚要按照阶段顺序依次执行,先到达、再拜堂、再吃酒席…:

public class PhaserDemo {

    static MarriagePhaser phaser = new MarriagePhaser();

    // 定义结婚阶段类
    static class MarriagePhaser extends Phaser {
        // 定义每个阶段要执行的任务, 返回值为为true时,代表phaser终止,否则继续执行
        @Override
        protected boolean onAdvance(int phase, int registeredParties) {
            switch (phase) {
                case 0:
                    System.out.println("所有人都到齐了!共有" + registeredParties + "人");
                    System.out.println();
                    return false;
                case 1:
                    System.out.println("新郎新娘拜堂!共有" + registeredParties + "人");
                    System.out.println();
                    return false;
                case 2:
                    System.out.println("所有人酒席吃完了!共有" + registeredParties + "人");
                    System.out.println();
                    return false;
                case 3:
                    System.out.println("所有人都离开了!共有" + registeredParties + "人");
                    System.out.println();
                    return false;
                case 4:
                    System.out.println("新郎新娘入洞房!共有" + registeredParties + "人");
                    System.out.println();
                    return true;
            }

            return super.onAdvance(phase, registeredParties);
        }
    }

    // 定义人线程
    static class Person extends Thread {

        Person (String name) {
            setName(name);
        }

        // 到达现场
        private void arrive() {
            System.out.println(getName() + "到达");
            phaser.arriveAndAwaitAdvance(); // 到达并等待
        }
        // 拜堂
        private void chapel() {
            if (getName().equals("新郎") || getName().equals("新娘")) {
                System.out.println(getName() + "拜堂了");
                phaser.arriveAndAwaitAdvance();
            } else {
                phaser.arriveAndDeregister();
            }
        }
        // 酒席
        private void eat() {
            if (!getName().equals("新郎") && !getName().equals("新娘")) {
                phaser.register();
            }
            System.out.println(getName() + "吃了");
            phaser.arriveAndAwaitAdvance();
        }
        // 离开
        private void leave() {
            System.out.println(getName() + "离开了");
            phaser.arriveAndAwaitAdvance();
        }
        // 洞房
        private void papapa() {
            if (getName().equals("新郎") || getName().equals("新娘")) {
                System.out.println(getName() + "洞房了");
                phaser.arriveAndAwaitAdvance();
            }else {
                phaser.arriveAndDeregister();
            }
        }
        @Override
        public void run() {
            arrive();
            chapel();
            eat();
            leave();
            papapa();
        }
    }

    public static void main(String[] args) {
        phaser.bulkRegister(7);
        for(int i=0; i<5; i++) {
            new Thread(new Person("p" + i)).start();
        }

        new Thread(new Person("新郎")).start();
        new Thread(new Person("新娘")).start();
    }
}

执行结果如下:

p0到达
新娘到达
新郎到达
p4到达
p3到达
p2到达
p1到达
所有人都到齐了!共有7人

新郎拜堂了
p0吃了
p2吃了
p4吃了
新娘拜堂了
p3吃了
p1吃了
新郎新娘拜堂!共有7人

新娘吃了
新郎吃了
p3离开了
p0离开了
p1离开了
p4离开了
p2离开了
所有人酒席吃完了!共有7人

新娘离开了
新郎离开了
所有人都离开了!共有2人

新郎洞房了
新娘洞房了
新郎新娘入洞房!共有2人

Semaphore

Semaphore 是信号量的意思,也成为信号灯(红绿灯),用来保证两个或多个关键代码段不被并发调用;类似锁,但是可以限制并发线程的数量。常用于限流。

public class SemaphoreDemo {

    public static void main(String[] args) {

        // 1盏灯,同时只允许一个线程执行
        Semaphore semaphore = new Semaphore(1);
        for (int i = 0; i < 3; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println("T"+ finalI +" run...");
                    Thread.sleep(200);
                    System.out.println("T"+ finalI +" run...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }).start();
        }
    }
}

Exchanger

交换两个线程的信息(只能是两个线程)。

// 交换线程0与线程1的装备
public class ExchangerDemo {

    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                try {
                    String threadName = Thread.currentThread().getName();
                    String exchange = exchanger.exchange( threadName + "的装备");
                    System.out.println(threadName + " = " + exchange);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "线程" + i).start();
        }
    }

}

结果:

线程0 = 线程1的装备
线程1 = 线程0的装备

LockSupport

LockSupport 是比较低级的工具方法,不过使用起来也很方便,相比notify,它可以指定某个thread进行唤醒。

public class LockSupportDemo {

    public static void main(String[] args) throws InterruptedException {
        // LockSupport 拥有park与unpark方法,
        // park的含义为停车,调用此方法的线程将会进入阻塞状态
        // unpark 则可用于唤醒已经park的线程,此方法可以指定要唤醒的线程,比wait和notify更加灵活

        Thread t = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("---" + i + "---");
                if (i == 5) {
                    LockSupport.park();
                }
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        // 注意,unpark将会将线程的park状态置为unpark
        // 调用一次后,再次调用park则无法进行线程阻塞
        // LockSupport.unpark(t);
        TimeUnit.SECONDS.sleep(8);
        System.out.println("-------after 8 seconds------");
        LockSupport.unpark(t); // 需要指定线程

    }

}
上一页锁的分类与对应的Java实现下一页JUC: AtomicXXX

最后更新于2年前

这有帮助吗?