Java多线程系列-CountDownLatch
来源:互联网 发布:计算机编程历史 编辑:程序博客网 时间:2024/06/07 21:58
概述
JDK中提供了一些用于线程之间协同等待的工具类,CountDownLatch和CyclicBarrier就是最典型的两个线程同步辅助类。下面分别详细介绍这两个类,以及他们之间的异同点。
CountDownLatch类
CountDownLatch顾名思义:倒计数锁存器。没错,他就是一个计数器,并且是倒着计数的。他的应用场景如下:
一个任务A,他需要等待其他的一些任务都执行完毕之后它才能执行。就比如说赛跑的时候,发令员需要等待所有运动员都准备好了才能发令,否则不被K才怪嘞!
此时CountDownLatch就可以大展身手了。
常用操作
本节介绍CountDownLatch的基本操作函数。
构造函数
函数签名如下:
1
public CountDownLatch(int count)
用一个给定的数值初始化CountDownLatch,之后计数器就从这个值开始倒计数,直到计数值达到零。
await函数
await函数用两种形式,签名分别如下:
12
public void await() throws InterruptedExceptionpublic boolean await(long timeout, TimeUnit unit)
这两个函数的作用都是让线程阻塞等待其他线程,直到CountDownLatch的计数值变为0才继续执行之后的操作。区别在于第一个函数没有等待时间限制,可以等到天荒地老,海枯石烂,第二个函数给定一个等待超时时间,超过该时间就直接放弃了,并且第二个函数具有返回值,超时时间之内CountDownLatch的值达到0就返回true,等待时间结束计数值都还没达到0就返回false。这两个操作在等待过程中如果等待的线程被中断,则会抛出InterruptedException异常。
countDown函数
这个函数用来将CountDownLatch的计数值减一,函数签名如下:
1
public void countDown()
需要说明的是,如果调用这个函数的时候CountDownLatch的计数值已经为0,那么这个函数什么也不会做。
getCount函数
该函数用来获取当前CountDownLatch的计数值,函数签名如下:
1
public void countDown()
模拟实验
理论知识讲完了,需要真枪实战地来演示一下这个类的作用,我们就以下面这个场景为例子,用CountDownLatch来实现这个需求:
有5个运动员赛跑,开跑之前,裁判需要等待5个运动员都准备好才能发令,并且5个运动员准备好之后也都需要等待裁判发令才能开跑。
首先分析一下依赖关系:
裁判发令 -> 5个运动员都准备好;
5个运动员开跑 -> 裁判发令。
好,依赖关系已经出来了,代码实现:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
package com.winwill.test;import java.util.Random;import java.util.concurrent.CountDownLatch;/** * @author qifuguang * @date 15/8/24 23:35 */public class TestCountDownLatch { private static final int RUNNER_NUMBER = 5; // 运动员个数 private static final Random RANDOM = new Random(); public static void main(String[] args) { // 用于判断发令之前运动员是否已经完全进入准备状态,需要等待5个运动员,所以参数为5 CountDownLatch readyLatch = new CountDownLatch(RUNNER_NUMBER); // 用于判断裁判是否已经发令,只需要等待一个裁判,所以参数为1 CountDownLatch startLatch = new CountDownLatch(1); for (int i = 0; i < RUNNER_NUMBER; i++) { Thread t = new Thread(new Runner((i + 1) + "号运动员", readyLatch, startLatch)); t.start(); } try { readyLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } startLatch.countDown(); System.out.println("裁判:所有运动员准备完毕,开始..."); } static class Runner implements Runnable { private CountDownLatch readyLatch; private CountDownLatch startLatch; private String name; public Runner(String name, CountDownLatch readyLatch, CountDownLatch startLatch) { this.name = name; this.readyLatch = readyLatch; this.startLatch = startLatch; } public void run() { int readyTime = RANDOM.nextInt(1000); System.out.println(name + ":我需要" + readyTime + "秒时间准备."); try { Thread.sleep(readyTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + ":我已经准备完毕."); readyLatch.countDown(); try { startLatch.await(); // 等待裁判发开始命令 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + ":开跑..."); } }}
运行结果如下:
1号运动员:我需要389秒时间准备.
2号运动员:我需要449秒时间准备.
3号运动员:我需要160秒时间准备.
4号运动员:我需要325秒时间准备.
5号运动员:我需要978秒时间准备.
3号运动员:我已经准备完毕.
4号运动员:我已经准备完毕.
1号运动员:我已经准备完毕.
2号运动员:我已经准备完毕.
5号运动员:我已经准备完毕.
裁判:所有运动员准备完毕,开始…
1号运动员:开跑…
5号运动员:开跑…
2号运动员:开跑…
4号运动员:开跑…
3号运动员:开跑…
可以看到,一切都是如此地完美,运动员准备好了之后裁判才发令,裁判发令之后运动员才开跑。
- Java多线程系列-CountDownLatch
- Java多线程系列-CountDownLatch
- Java多线程系列9(CountDownLatch)
- java多线程系列(八)---CountDownLatch和CyclicBarrie
- 【Java】多线程系列(二)之CountDownLatch的使用
- Java多线程系列(九)—CountDownLatch源码分析
- JAVA多线程系列--并发工具类(CountDownLatch, CyclicBarrier, Semaphore,Exchanger)
- Java多线程之CountDownLatch
- Java多线程之CountDownLatch
- java 多线程 CountDownLatch用法
- Java多线程之CountDownLatch
- JAVA多线程之CountDownLatch
- java 多线程 CountDownLatch用法
- Java多线程之CountDownLatch
- java 多线程 CountDownLatch用法
- java 多线程 CountDownLatch用法
- java 多线程 CountDownLatch用法
- Java多线程之CountDownLatch
- (49)Java学习笔记——多线程 / 内部匿名类使用多线程 / 定时器
- Linux使用Composer安装yii2的方法及bug处理
- 构建一个复数类
- ubuntu14.04 +nginx+php5-fpm
- uva 10746Crime Wave - The Sequel
- Java多线程系列-CountDownLatch
- Arduino pro mini 烧录程序
- 使用API的大集合和总结
- pm2 相关命令
- java-打印九九乘法表
- Wikipedia viewer
- 编程书籍阅读随谈(第三篇)
- Java多线程系列-CyclicBarrier
- visual Studio 2010 下 DirectX 10.0 SDK 安装配置过程