серия многопоточности Java: CountDownLatch

Java задняя часть игра

В этой статье будут представлены основные сведения о CountDownLatch, классе инструмента синхронизации, а также на примерах показано, как использовать этот инструмент.

CountDownLatchjava.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计数减一之后,继续加载其他数据...");
};

Метод запуска выглядит следующим образом: при вызовеhandle()метод выполняется послеcount.countDown();,ПозволятьCountDownLatchСчетчик уменьшается на 1. После уменьшения счетчика на 1 можно продолжать загрузку дополнительных данных, не затрагивая текущий поток

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);
    }
}

Код других классов загрузки данных публиковаться не будет, а время сна другое.

начать игру

Запустите игровой класс следующим образом, переданный через конструкторCountDownLatchcounter, а затем выполнить его в методе runcount.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.可以开始游戏...

Адрес исходного кода кейса:GitHub.com/радуга большая/приходите…

Если интересно, нажмите звездочку