这篇文章将介绍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. Python List reverse()方法

    reverse() 函数用于反向列表中元素,参数 NA,该方法没有返回值,但是会对列表的元素进行反向排序,原来的列表被改变,生成新的列表. 例子:list1 = ['Google', 'Runoob' ...

  2. HIVE-利用ow_number() OVER(PARTITION BY)函数介绍求TOP-K

    http://blog.csdn.net/631799/article/details/7419797 第一句话: select row_number() over (partition by mon ...

  3. ping错误详解

    在网络中Ping 是一个十分好用的TCP/IP工具,它主要的功能是用来检测网络的连通情况和分析网络速度. 输入 ping /? 例出ping的参数 使用Ping检查连通性有五个步骤 1. 使用ipco ...

  4. java代码异常处理

    总结:运用throw和throws抛出异常,在哪一种情况下该怎么抛出异常.重要 package com.b; //异常中throwe和throws的用法 public class yz { publi ...

  5. mongoTemplate操作内嵌文档

    关系型数据库中,表与表的关联关系有1:1,也有1:n的.在java的面向对象的世界里就是主对象嵌子对象,与主对象嵌集合<子对象>的两种形式. 主对象嵌子对象操作: 新增.修改都直接用如下方 ...

  6. DVWA平台v1.9-Command Injection

    命令拼接: &:简单的拼接,第一条命令和第二条命令间没有什么制约关系 &&:第一条命令执行成功了,才会执行第二条命令 |:第一条命令的输出作为第二条命令的输入 ||:第一条命令 ...

  7. Python类(八)-类的起源

    首先用type()看一下类和实例化对象的类型 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" class Person(obj ...

  8. Ubuntu中vi命令的使用

    指今说明: 进入 vi 的命令vi filename: 打开或新建文件,并将光标置于第一行首 vi +n filename: 打开文件,并将光标置于第n行首 vi + filename: 打开文件,并 ...

  9. [原]实例-简单设计&精简代码&复用代码

    引言 本文以实际项目为例谈一谈我个人对于软件开发的理解,偏细节   软件项目B 基于.net平台,使用WPF框架,c#语言,MVVM模式开发的桌面软件 该软件支持可视化的设计器功能,允许所见即所得的方 ...

  10. js和jQuery常用选择器

    笔者觉得js是前台基础中的基础,而其选择器则是js基础中的基础,因长期使用框架导致js生疏,所有查资料,回顾一下js的常用选择器: 1.document.getElementById("id ...