这篇文章将介绍CountDownLatch这个同步工具类的基本信息以及通过案例来介绍如何使用这个工具。

CountDownLatch是java.util.concurrent包下面的一个工具类,可以用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。 它可以允许一个或者多个线程等待其他线程完成操作。

案例

模拟游戏一开始需要加载一些基础数据后才能开始游戏,基础数据加载完可以继续加载其他数据。基础数据包含人物、地图、背景、物品等等。

解决方案

利用CountDownLatch来实现,基础数据加载完毕后,CountDownLatch计数器进行减一操作。当CountDownLatch计数器为0时,表示可以开始游戏。 示意图如下

定义抽象类

定义抽象类AbstractDataRunnable并实现Runnable接口

抽象类包含两个属性

private String name;
private CountDownLatch count;

通过构造函数初始化两个属性

public AbstractDataRunnable(String name, CountDownLatch count) {
this.name = name;
this.count = count;
}

定义方法,提供一个抽象方法handle()供子类去实现,getName()afterCountDown()提供默认的实现。

public String getName() {
return name;
} public abstract void handle() throws InterruptedException; public void afterCountDown(){
System.out.println(this.getName() + ":CountDownLatch计数减一之后,继续加载其他数据...");
};

run方法如下,在调用handle()方法之后执行count.countDown();,让CountDownLatch计数器进行减一操作.计数器减一之后可以继续加载额外的数据,并不影响当前线程

public void run() {
try {
System.out.println(this.getName()+" 开始加载...");
Long l1 = System.currentTimeMillis();
handle();
Long l2 = System.currentTimeMillis();
System.out.println(this.getName()+" 加载完成,花费时间:"+(l2-l1));
} catch (Exception e){
e.printStackTrace();
} finally {
count.countDown();
}
afterCountDown();
}

定义一些数据加载类

背景数据加载类如下,实现了抽象类AbstractDataRunnablehandle()方法,在handle()方法休眠了2秒

public class BackGroundData extends AbstractDataRunnable {

    public BackGroundData(String name, CountDownLatch count) {
super(name, count);
} @Override
public void handle() throws InterruptedException {
//模拟加载时间,2秒
Thread.sleep(2000);
}
}

其他数据加载类代码就不贴出来了,睡眠的时间不同而已

开始游戏

开始游戏类如下,通过构造函数传入CountDownLatch计数器,然后在run方法中执行count.await();方法进行等待基础数据加载完毕。

class StartGame implements Runnable{
private CountDownLatch count; public StartGame(CountDownLatch count) {
this.count = count;
} @Override
public void run() {
try {
System.out.println("开始加载基础数据...");
Long l1 = System.currentTimeMillis();
count.await();
Long l2 = System.currentTimeMillis();
System.out.println("基础数据加载完毕,总共花费时长:"+(l2-l1)+".可以开始游戏...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

测试

public static void main(String[] args) throws IOException {
CountDownLatch count = new CountDownLatch(4); //主线程
Thread startGameThread = new Thread(new StartGame(count));
startGameThread.start(); //加载数据线程
Thread mapThread = new Thread(new MapData("地图",count));
Thread goodsThread = new Thread(new GoodsData("物品",count));
Thread personageThread = new Thread(new PersonageData("人物",count));
Thread backGroundThread = new Thread(new BackGroundData("背景",count)); mapThread.start();
goodsThread.start();
personageThread.start();
backGroundThread.start(); System.in.read();
}

测试结果内容

开始加载基础数据...
地图 开始加载...
物品 开始加载...
人物 开始加载...
背景 开始加载...
人物 加载完成,花费时间:1000
人物:CountDownLatch计数减一之后,继续加载其他数据...
背景 加载完成,花费时间:2000
背景:CountDownLatch计数减一之后,继续加载其他数据...
物品 加载完成,花费时间:2501
物品:CountDownLatch计数减一之后,继续加载其他数据...
地图 加载完成,花费时间:3001
地图:CountDownLatch计数减一之后,继续加载其他数据...
基础数据加载完毕,总共花费时长:3003.可以开始游戏...

案例源代码地址:https://github.com/rainbowda/learnWay/tree/master/learnConcurrency/src/main/java/com/learnConcurrency/utils/countDownLatch

有兴趣的点个Star

java多线程系列:CountDownLatch的更多相关文章

  1. Java 多线程系列 CountDownLatch

    CountDownLatch 一个或多个线程等待其他线程完成操作后在在执行 CountDownLatch通过一个计数器来实现,await方法阻塞直到 countDown() 调用计数器归零之后释放所有 ...

  2. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

    概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...

  3. java多线程系列(八)---CountDownLatch和CyclicBarrie

    CountDownLatch 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线 ...

  4. Java多线程系列——计数器 CountDownLatch

    简介: CountDownLatch 是一个非常实用的多线程控制工具类,通常用来控制线程的等待,它可以让某个线程等待直到倒计时结束 CountDownLatch 提供了两个主要的方法,await(). ...

  5. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  6. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  7. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

  8. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

  9. Java多线程系列目录(共43篇)

    最近,在研究Java多线程的内容目录,将其内容逐步整理并发布. (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线 ...

  10. Java多线程系列--“JUC锁”05之 非公平锁

    概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...

随机推荐

  1. Shiro-Session

    概述 Shiro提供了完整的企业级会话管理功能,不依赖于底层容器(如web容器tomcat),不管JavaSE还是JavaEE环境都可以使用,提供了会话管理.会话事件监听.会话存储/持久化.容器无关的 ...

  2. mysql_union all 纵向合并建表_20170123

    年前事情比较多,博客不能每天更新了. 1.union all 纵向建表和left join 横向建表的数据结构区别 先贴代码 后面再补充 (#销售确认额 SELECT '05收货销售额' AS 标识, ...

  3. java 收集linux信息

    public class MachineCollector  implements Runnable{  private static int DEFAULT_INTERVAL = 30;  priv ...

  4. Oracl使用总结二

    1.ORA-00972: 标识符过长 错误排除 可能原因: 1.如果是拼接成的sql语句,请查找传递参数时字符型字段是否两边少了引号.2.数据库表名太长了,附各种类型的数据库表名长度: SQLSERV ...

  5. (C#)把磁盘目录树加载在窗体菜单中

    这又是一个没有技术含量的代码.写出来只是玩玩,所以也不敢放在首页. 这里有个问题,是获取文件/文件夹的图标.使用 System.Drawing.Icon.ExtractAssociatedIcon 只 ...

  6. Ubuntu 16.04 LTS制作本地源

    平时apt-get install安装软件时,下载的deb文件都会存放在/var/cache/apt/archives/下,没有网络时就需要将这些deb制作成本地源.另外,如果在本机架一个简单的网络服 ...

  7. L2-014. 列车调度(set的使用,最长递增子序列)

    L2-014. 列车调度 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 火车站的列车调度铁轨的结构如下图所示. Figure ...

  8. SpringMVC—对Ajax的处理(含 JSON 类型)(3)

    五.服务器端的 SpringMVC 如何返回 JSON 类型的字符串. 请求: $("#testJson8").click(function () {    $.ajax({   ...

  9. JavaScript组合设模式--改进上述引入的例子

    对于组合设计模式: (1)组合模式中把对象分为两种(组合对象,和叶子对象) (2)组合对象和叶子对象实现:同一批操作 (3)对组合对象执行的操作可以向下传递到叶子节点进行操作 (4)这样就会弱化类与类 ...

  10. 安卓SQLite数据库操作(上)

    安卓系统自带数据库,名为SQLite.这篇文章我们用一个Demo来讲解安卓操作数据库的例子. By the way, 安卓创建的数据库文件存放在/data/data/<包名>/databa ...