JUC的多线程辅助类非常多,这里我们介绍三个:

  1. CountDownLatch(倒计数器)

  2. CyclicBarrier(循环栅栏)

  3. Semaphore(信号量)

1. CountDownLatch

CountDownLatch是一个非常实用的多线程控制工具类,应用非常广泛。

例如:在手机上安装一个应用程序,假如需要5个子进程检查服务授权,那么主进程会维护一个计数器,初始计数就是5。用户每同意一个授权该计数器减1,当计数减为0时,主进程才启动,否则就只有阻塞等待了。

CountDownLatch中count down是倒数的意思,latch则是门闩的含义。整体含义可以理解为倒数的门栓,似乎有一点“三二一,芝麻开门”的感觉。CountDownLatch的作用也是如此。

常用的就下面几个方法:

new CountDownLatch(int count)  //实例化一个倒计数器,count指定初始计数
countDown()  // 每调用一次,计数减一
await()  //等待,当计数减到0时,阻塞线程(可以是一个,也可以是多个)并行执行

案例:6个同学陆续离开教室后值班同学才可以关门。  

public class CountDownLatchDemo {/*** main方法也是一个进程,在这里是主进程,即上锁的同学** @param args*/public static void main(String[] args) throws InterruptedException {// 初始化计数器,初始计数为6CountDownLatch countDownLatch = new CountDownLatch(6);for (int i = 0; i < 6; i++) {new Thread(()->{try {// 每个同学墨迹几秒钟TimeUnit.SECONDS.sleep(new Random().nextInt(5));System.out.println(Thread.currentThread().getName() + " 同学出门了");// 调用countDown()计算减1countDownLatch.countDown();} catch (InterruptedException e) {e.printStackTrace();}}, String.valueOf(i)).start();}// 调用计算器的await方法,等待6位同学都出来countDownLatch.await();System.out.println("值班同学锁门了");}
}

2. CyclicBarrier

从字面上的意思可以知道,这个类的中文意思是“循环栅栏”。大概的意思就是一个可循环利用的屏障。该命令只在每个屏障点运行一次。若在所有参与线程之前更新共享状态,此屏障操作很有用。

常用方法:

  1. CyclicBarrier(int parties, Runnable barrierAction) 创建一个CyclicBarrier实例,parties指定参与相互等待的线程数,barrierAction一个可选的Runnable命令,该命令只在每个屏障点运行一次,可以在执行后续业务之前共享状态。该操作由最后一个进入屏障点的线程执行。

  2. CyclicBarrier(int parties) 创建一个CyclicBarrier实例,parties指定参与相互等待的线程数。

  3. await() 该方法被调用时表示当前线程已经到达屏障点,当前线程阻塞进入休眠状态,直到所有线程都到达屏障点,当前线程才会被唤醒。

案例:组队打boss过关卡游戏。

注意:所有的"过关了"都是由最后到达await方法的线程执行打印的。

public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {System.out.println(Thread.currentThread().getName() + " 过关了");});for (int i = 0; i < 3; i++) {new Thread(()->{try {System.out.println(Thread.currentThread().getName() + " 开始第一关");TimeUnit.SECONDS.sleep(new Random().nextInt(4));System.out.println(Thread.currentThread().getName() + " 开始打boss");cyclicBarrier.await();System.out.println(Thread.currentThread().getName() + " 开始第二关");TimeUnit.SECONDS.sleep(new Random().nextInt(4));System.out.println(Thread.currentThread().getName() + " 开始打boss");cyclicBarrier.await();System.out.println(Thread.currentThread().getName() + " 开始第三关");TimeUnit.SECONDS.sleep(new Random().nextInt(4));System.out.println(Thread.currentThread().getName() + " 开始打boss");cyclicBarrier.await();} catch (Exception e) {e.printStackTrace();}}, String.valueOf(i)).start();}}
}

3. Semaphore

Semaphore翻译成字面意思为 信号量,Semaphore可以控制同时访问的线程个数。非常适合需求量大,而资源又很紧张的情况。比如给定一个资源数目有限的资源池,假设资源数目为N,每一个线程均可获取一个资源,但是当资源分配完毕时,后来线程需要阻塞等待,直到前面已持有资源的线程释放资源之后才能继续。

常用方法:

public Semaphore(int permits) // 构造方法,permits指资源数目(信号量)
public void acquire() throws InterruptedException // 占用资源,当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时。
public void release() // (释放)实际上会将信号量的值加1,然后唤醒等待的线程。

信号量主要用于两个目的:

  1. 多个共享资源的互斥使用。

  2. 用于并发线程数的控制。保护一个关键部分不要一次输入超过N个线程。

案例:6辆车抢占3个车位

public class SemaphoreDemo {public static void main(String[] args) {// 初始化信号量,3个车位Semaphore semaphore = new Semaphore(3);// 6个线程,模拟6辆车for (int i = 0; i < 6; i++) {new Thread(()->{try {// 抢占一个停车位semaphore.acquire();System.out.println(Thread.currentThread().getName() + " 抢到了一个停车位!!");// 停一会儿车TimeUnit.SECONDS.sleep(new Random().nextInt(10));System.out.println(Thread.currentThread().getName() + " 离开停车位!!");// 开走,释放一个停车位semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}, String.valueOf(i)).start();}}
}

05_JUC强大的辅助类相关推荐

  1. Eureka的InstanceInfoReplicator类(服务注册辅助工具)

    关于服务注册 以下图片来自Netflix官方,图中显示Eureka Client会向注册中心发起Get Registry请求来获取服务列表: 以Spring Cloud的Edgware.RELEASE ...

  2. Java中使用JCOM操作Word/Excel对象

    通过使用COM技术,我们用微软Office应用程序能够建立很多应用程序扩展,但是Java开发人员却无法享受它带来的便利--除非他们拥有方便的Java访问COM的途径(Java-to-COM桥).使用J ...

  3. Java线程(五):Executors、ThreadFactory

    Executors public class Executors 一个功能非常强大的辅助类. 此包中所定义的 Executor.ExecutorService.ScheduledExecutorSer ...

  4. 大数据学习之路 JUC篇

    大数据学习之路 JUC篇(1) 前提说明 本人是一名学生,茫茫it行业的一名卑微的小白,这是我第一次写博客.其原因是学着学着知识发现回顾的时候差不多全忘记了!!为了总结.复习自己以往学到过的有关大数据 ...

  5. android app数据存储,基于Android开发的APP数据存储研究

    谢原武+龙文 摘要: 作为一个完整的应用程序,数据存储操作是必不可少的.Android系统一共提供了四种数据存储方式分别为File文件存储.Shared Preferences存储.ContentPr ...

  6. 尚硅谷宋红康2021JUC

    一. JUC概述 什么是JUC? (1)java并发编程包中的一些工具类,这些工具类可以更加方便实现并发编程操作. (2)JUC 就是 java.util .concurrent 工具包的简称.这是一 ...

  7. JUC基础(周阳老师笔记

    目录 一.JMM 1.volatile 2.加载代码练习: 二.JUC基础 1.什么是进程/线程,并发/并行 进程/线程 并发/并行 2.线程的状态 3.线程 操作 资源类 4.Lambda表达式 j ...

  8. JUC 2020 周阳 尚硅谷 学习笔记

    这里写目录标题 一 JUC 介绍 1 进程线程介绍介绍 2 并发并行的介绍 3 wait 和 sleep的区别 4 线程的状态 二 卖票算法的企业级模板实现 企业级简单实现(synchronized) ...

  9. JUC笔记之尚硅谷周阳老师思维导图整理

    文章目录 1. JUC 是什么 2. Lock 接口 3. Lambda表达式复习--详情请看 on java 8 4. 线程间通信 5. 线程间定制化调用通信 6.NotSafeDemo 7.多线程 ...

最新文章

  1. 网站外部链接优化如何进一步提升?
  2. .NET Core使用EF分页查询数据报错:OFFSET语法错误问题
  3. java 捕获特定异常_java – 使用特定消息捕获异常
  4. web安全day48:session和cookie、同源策略的初步理解
  5. 学习笔记(1):《微电子器件》陈星弼(第四版)第1章 半导体物理基础及基本方程
  6. 主播被MCN解约并判违约金60万
  7. GPS基带P码处理总结——FPGA实现的关键点
  8. CAS单点登录:CAS客户端搭建(整合Shiro和Spring Boot)
  9. python for循环求1到100的和_python如何计算1到100的和(用for循环)
  10. IDEA 2018.3.3 有效期至 2100
  11. 2017ACM-ICPC亚洲区域赛(西安站)
  12. 【汇正财经】什么是板块轮动?有什么规律?
  13. import cv2 报错(linux环境)ImportError: libGL.so.1: cannot open shared object file: No such file or direc
  14. 给iOS App减肥
  15. Variant数据类型
  16. 语音信号处理第三章:
  17. Http Header里的Content-Type
  18. 习题:有100个学生种100棵树,其中高中生每人种3棵树,初中生每人种1棵树,小学生每3人种1棵树,问高中生、初中生、小学生各有多少人?
  19. Oracle ORA-01017: invalid username/password;解决完一个12560又来一个
  20. 计算机 打印机型号编码不可用,打印机型号编码显示不可用

热门文章

  1. php 微信支付分 教程
  2. p29 p30 p31 p32
  3. STM32之BKP原理
  4. 通过3SAT证明支配集是NPC问题
  5. NPC内网穿透教程-入门
  6. 计算机视觉中头部姿态估计的研究综述--Head Pose Estimation in Computer Vision - A Survey
  7. 网络工程项目报价单应该怎么写?记住这6个步骤准没错!
  8. 人工智能于交通系统而言
  9. QLU ACM2018新生赛
  10. 跟随器为何要加反馈电阻?