This article introduces basic information about the synchronization tool class CountDownLatch and provides a case study on how to use the tool.

CountDownLatch is a utility class under the java.util.Concurrent package that can be used to coordinate synchronization between multiple threads, or for communication between threads (rather than as a mutual exclusion). It allows one or more threads to wait for other threads to complete operations.

case

Simulation games need to load some basic data to start the game, after loading the basic data can continue to load other data. Basic data includes people, maps, backgrounds, objects, and so on.

The solution

CountDownLatch is used to achieve this. After the basic data is loaded, the CountDownLatch counter is reduced by one. When the CountDownLatch counter is 0, the game is ready to start. The schematic diagram is as follows

Defining an Abstract class

Define AbstractDataRunnable and implement the Runnable interface

The abstract class contains two properties

private String name;
private CountDownLatch count;
Copy the code

Initialize two properties via constructors

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

Define methods that provide an abstract method handle() for subclasses to implement, with getName() and afterCountDown() providing default implementations.

public String getName(a) {
    return name;
}

public abstract void handle(a) throws InterruptedException;

public void afterCountDown(a){
    System.out.println(this.getName() + ": After the CountDownLatch count is reduced by one, continue loading other data...");
};
Copy the code

The run method looks like this, and count.countdown () is executed after calling handle(); To enable the CountDownLatch counter to decrease by one. After the counter is reduced by one, additional data can continue to be loaded without affecting the current thread

public void run(a) {
    try {
        System.out.println(this.getName()+"Start loading...");
        Long l1 = System.currentTimeMillis();
        handle();
        Long l2 = System.currentTimeMillis();
        System.out.println(this.getName()+"Load complete, take time :"+(l2-l1));
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        count.countDown();
    }
    afterCountDown();
}
Copy the code

Define some data loading classes

The handle() method of AbstractDataRunnable is implemented. The handle() method sleeps for 2 seconds

public class BackGroundData extends AbstractDataRunnable {

    public BackGroundData(String name, CountDownLatch count) {
        super(name, count);
    }

    @Override
    public void handle(a) throws InterruptedException {
        // Analog load time, 2 seconds
        Thread.sleep(2000); }}Copy the code

Other data loading class code will not be posted, sleep time is different

Start the game

To start the game class, pass the CountDownLatch counter through the constructor, and then execute count.await() in the run method; Method to wait until the basic data is loaded.

class StartGame implements Runnable{
    private CountDownLatch count;

    public StartGame(CountDownLatch count) {
        this.count = count;
    }

    @Override
    public void run(a) {
        try {
            System.out.println("Start loading base data...");
            Long l1 = System.currentTimeMillis();
            count.await();
            Long l2 = System.currentTimeMillis();
            System.out.println("Total time spent after basic data is loaded :"+(l2-l1)+".Can start the game...");
        } catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code

test

public static void main(String[] args) throws IOException {
    CountDownLatch count = new CountDownLatch(4);

    / / main thread
    Thread startGameThread = new Thread(new StartGame(count));
    startGameThread.start();

    // Load the data thread
    Thread mapThread = new Thread(new MapData("Map",count));
    Thread goodsThread = new Thread(new GoodsData("Goods",count));
    Thread personageThread = new Thread(new PersonageData("Character",count));
    Thread backGroundThread = new Thread(new BackGroundData("Background",count));


    mapThread.start();
    goodsThread.start();
    personageThread.start();
    backGroundThread.start();

    System.in.read();
}
Copy the code

Test result content

Start loading base data... The map starts loading... Items start loading... Characters start loading... Background starts loading... Figure :CountDownLatch After the count is reduced by one, continue to load more data... Background load completed, time :2000 Background: After the CountDownLatch count is reduced by one, continue loading other data... Item load completed, time :2501 Item :CountDownLatch count reduced by one, continue loading additional data... Map :CountDownLatch count is reduced by one, continue loading other data... After loading basic data, total time :3003.Copy the code

Case source code address: github.com/rainbowda/l…

Click Star if you’re interested