zoukankan      html  css  js  c++  java
  • java多线程系列:CountDownLatch

    这篇文章将介绍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

  • 相关阅读:
    【华为云技术分享】华为云HiLens全面升级,端云协同多模态AI应用开发利器
    【华为云技术分享】MongoDB经典故障系列四:调整oplog大小,引起从库宕机怎么办?
    使用体验神似VS Code?三步带你了解华为云CloudIDE前世今生
    nginx 下配置禅道
    如何在HTTPS 网页中引入HTTP资源: Mixed Content?
    stocket和webstocket的区别
    [转载]input[type=file]在移动端各浏览器无法适配打开相机的问题。
    视频和图片的存储(阿里云OSS还是七牛?)
    VUE 和AngularJS 开发SPA能支持APP内嵌么
    【PHP7.1】使用OpenSSL来代替Mcrypt加解密【原创】
  • 原文地址:https://www.cnblogs.com/fixzd/p/9556675.html
Copyright © 2011-2022 走看看