目录

一、引言

二、Semaphore

三、countdownlatch

四、cyclicbarrier

五、exchanger

六、总结


一、引言

在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier、Semaphore和exchanger。

Semaphore:一个计数信号量
CountDownLatch:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 
CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 
Exchanger:方便了两个共同操作线程之间的双向交换

下面举例子分别介绍这些类的使用场景

二、Semaphore

Semaphore 信号量对象管理的信号就像令牌,构造时传入个数,总数就是控制并发的数量。我们需要控制并发的代码,执行前先获取信号(通过acquire获取信号许可),执行后归还信号(通过release归还信号许可)。每次acquire成功返回后,Semaphore可用的信号量就会减少一个,如果没有可用的信号,acquire调用就会阻塞,等待有release调用释放信号后,acquire才会得到信号并返回。

如果Semaphore管理的信号量为1个,那么就退化到互斥锁了;如果多于一个信号量,则主要用于控制并发数。与通过控制线程数来控制并发数的方式相比,通过Semaphore来控制并发数可以控制得更加细粒度,因为真正被控制最大并发的代码放到acquire和release之间就行了。

使用场景,食堂做饭只有四个切菜刀,有十个人要切十个菜,限制菜刀数量抢到的先切菜,切完再给别人。

public class Testsemophore {public static void main(String[]args){final Semaphore semaphore = new Semaphore(3);for (int i=0;i<7;i++){new Thread(new Runnable() {public void run() {try {semaphore.acquire();System.out.println(Thread.currentThread().getName()+"获取到许可");Thread.sleep(1000);semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}}

输出结果:

Thread-0获取到许可
Thread-2获取到许可
Thread-1获取到许可
Thread-3获取到许可
Thread-4获取到许可
Thread-5获取到许可
Thread-6获取到许可

三、countdownlatch

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

其机制是:当多个(具体数量等于初始化CountDownLatch时的count参数的值)线程都达到了预期状态或完成预期工作时触发事件,其他线程可以等待这个事件来触发自己的后续工作。这里需要注意的是,等待的线程可以是多个,即CountDownLatch是可以唤醒多个等待的线程的。达到自己预期状态的线程会调用CountDownLatch的countDown方法,而等待的线程会调用CountDownLatch的await方法。

CountDownLatch 很适合用来将一个任务分为n个独立的部分,等这些部分都完成后继续接下来的任务,CountDownLatch 只能出发一次,计数值不能被重置。

public class Testcutdownlatch {public static void main(String[] args) {final CountDownLatch latch = new CountDownLatch(3);new Thread(new Runnable() {public void run() {try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Waiter Released");}}).start();new Thread(new Runnable() {public void run() {try {Thread.sleep(1000);latch.countDown();Thread.sleep(1000);latch.countDown();Thread.sleep(1000);latch.countDown();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}

输出结果:

Waiter Released

四、cyclicbarrier

可以协同多个线程,让多个线程在这个屏障前等待,直到所有线程都达到了这个屏障时,再一起继续执行后面的动作。

CyclicBarrier适用于多个线程有固定的多步需要执行,线程间互相等待,当都执行完了,再一起执行下一步。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier

public class Testcyclicbarrier {public static void main(String[] args) {final CyclicBarrier barrier1 = new CyclicBarrier(2, new Runnable() {public void run() {System.out.println("BarrierAction 1 executed ");}});final CyclicBarrier barrier2 = new CyclicBarrier(2, new Runnable() {public void run() {System.out.println("BarrierAction 2 executed ");}});for (int i=0;i<3;i++){new Thread(new Runnable() {public void run() {try {Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+"waited barrier1");barrier1.await();Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+"waited barrier2");barrier2.await();} catch (InterruptedException e) {e.printStackTrace();}catch (BrokenBarrierException e) {e.printStackTrace();}}}).start();}}}

输出结果:

Thread-0waited barrier1
Thread-2waited barrier1
Thread-1waited barrier1
BarrierAction 1 executed
Thread-0waited barrier2
Thread-1waited barrier2
BarrierAction 2 executed

注意比较CountDownLatch和CyclicBarrier:

  (01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。

  (02) CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。

CountDownLatch 适用于一组线程和另一个主线程之间的工作协作。一个主线程等待一组工作线程的任务完毕才继续它的执行是使用 CountDownLatch 的主要场景;CyclicBarrier 用于一组或几组线程,比如一组线程需要在一个时间点上达成一致,例如同时开始一个工作。

五、exchanger

Exchanger 类方便了两个共同操作线程之间的双向交换;这样,就像具有计数为 2 的 CyclicBarrier,并且两个线程在都到达屏障时可以“交换”一些状态。(Exchanger 模式有时也称为聚集。)

Exchanger 通常用于一个线程填充缓冲(通过读取 socket),而另一个线程清空缓冲(通过处理从 socket 收到的命令)的情况。当两个线程在屏障处集合时,它们交换缓冲。

public class Testexchanger {public static void main(String[]args){final Exchanger exchanger = new Exchanger();//Action action=new Action();new Thread(new Runnable() {public void run() {try {Thread.sleep(1000);exchanger.exchange(Thread.currentThread().getName()+"data");System.out.println(Thread.currentThread().getName()+"我交给你了");} catch (InterruptedException e) {e.printStackTrace();}}}).start();new Thread(new Runnable() {public void run() {try {exchanger.exchange(Thread.currentThread().getName()+"data");System.out.println(Thread.currentThread().getName()+"我交给你了");} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}

输出结果:

Thread-0我交给你了
Thread-1我交给你了

六、总结

  • semaphore
  • countdownlatch
  • cyclicbarrier
  • exchanger

Java多线程(八)——多线程辅助功能类相关推荐

  1. java知识点八:时间日期类

    时间日期类 一.常用日期类 1.System类 2.Date类 3.SimpleDateFormat类 4.Calendar类 二.System类 比较常用的相关方法currentTimeMills( ...

  2. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

  3. java thread类_Java多线程原理及Thread类详解

    多线程原理 代码如下: 自定义线程类: 测试类: 流程图: 程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建.随着调用mt的对象的start方法,另外一 ...

  4. JAVA中的多线程(八):线程的优先级和yield方法

    JAVA中的多线程(八):线程的优先级和yield方法 优先级代表着抢资源的频率 所有线程默认优先级是5 yield()临时释放线程的执行权 1 class Demo implements Runna ...

  5. JavaSE基础二十:Java 多线程(线程基础知识、Java 多线程、Java 实现多线程(继承 Thread 类、实现 Runnable 接口、实现 Callable 接口))

    本章目录 1.基础知识准备 2.Java 多线程概述 3.Java 实现多线程 3.1.继承 Thread 类 如何开启新线程 Thread 类常用方法 多线程中的同步 Thread 类同步方法 多线 ...

  6. 基于Java多线程的打怪升级类游戏设计与开发

    摘要:本文论述了通过JAVA多线程.基于JAVA Swing的GUI图形用户界面设计.IO输入输出流.JDBC技术,实现了游戏系统的UI设计.游戏数据的存储.关卡的设置.用户头像的上传与更改.游戏数据 ...

  7. java里的多线程同步机制

    2019独角兽企业重金招聘Python工程师标准>>> 要说明线程同步问题首先要说明Java线程的两个特性,可见性和有序性.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通 ...

  8. Java并发与多线程

    1.多线程优点 资源利用率更好:文件读写操作 程序设计在某些情况下更简单: 程序响应更快:端口监听操作 2.多线程的代价 设计更复杂:多线程共享数据时尤其需要注意 上下文切换的开销: CPU 会在一个 ...

  9. Java基础21 多线程线程两种实现方式 锁

    一.多线程的概念 1.程序 :一个固定逻辑与数据的集合 就称为程序 例如淘宝 贪吃蛇小游戏 2.CPU: 中央处理器 主要用于协调程序与硬件进行配置的工作 3.并发与并行 1.并发(高并发) 在同一个 ...

  10. JAVA 笔记 10 多线程

    进程 与 线程 进程 进程资源分配的最小单位,CPU从磁盘中读取一段程序到内存中,该执行程序的实例就叫做进程; 一个程序如果被CPU多次读取到内存中,则变成多个独立的进程. 线程 线程是程序执行的最小 ...

最新文章

  1. TSNE-原理与实现
  2. 使用JConsole监控ActiveMQ
  3. 今天写了个Win32服务设置软件,呵呵,纯绿色软件
  4. [007] 详解 .NET 程序集
  5. 一个不错的讲解flex 3中自定义事件的文章
  6. mysql 子字符串函数_MySQL 内置字符串函数
  7. linux下为php开启oci8扩展(ubuntu14亲测可用)
  8. C# 获取项目程序路径的10种方法
  9. IDM(Internet Download Manager)下载各类安装包(github代码、python包)、软件、视频、文档的神器,居家必备良药
  10. python 正则处理经纬度度分秒转换
  11. javascript跨域
  12. 无本经营?2021做电商跨境shopee平台赚钱很轻松!
  13. MIPI CSI、DSI、UFS、C-PHY、D-PHY、M-PHY概念理解
  14. android突然断电丢失程序,a2sd+状态下应用程序丢失的解决方法详细解析
  15. linux怎么让cpu不自动降频,Win10 CPU自动降频怎么办?Win10下让CPU不降频设置方法
  16. shader拖尾_拖尾效果 - LouisSong - 博客园
  17. c语言lr分析器的设计与实现_ShinyJson实践之路:词法分析器的设计与实现
  18. 盘点国内EDA软件公司
  19. python利用turtle库绘制正方形绕一个顶点旋转
  20. 构建人工智能评测平台(体系)

热门文章

  1. 机器人图规划算法研究现状简述
  2. c语言如歌输出空字符,沈阳航空航天大学毕业设计(论文).doc
  3. 螺栓预紧力_斯姆勒知识讲解:螺栓预紧力的计算
  4. 边框border(HTML、CSS)
  5. 生产者消费者模型-管程法(Java)
  6. 字符串连接符(Java)
  7. 后缀转中缀表达式_中缀转后缀表达式代码实现(下)及计算器完整版
  8. 爬虫数据库一些简单的设计逻辑
  9. YARN组件详细介绍
  10. 跳转前暂停几秒js如何实现