java多线程countdownlatch_java多线程系列:CountDownLatch

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

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

9fddf739e8fe529d7370d33ad5907678.png

案例

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

解决方案

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

c78cd811fdd2c5cdd6aa0bf059c89fc3.png

定义抽象类

定义抽象类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();

}

定义一些数据加载类

背景数据加载类如下,实现了抽象类AbstractDataRunnable的handle()方法,在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.可以开始游戏...

有兴趣的点个Star

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值