Java Multithreading series: Learn Cyclicbarrier through PVP Games

Source: Internet
Author: User

Cyclicbarrier is a tool class under the Java.util.concurrent package that literally means a reusable (Cyclic) barrier (Barrier) that can be blocked when a set of threads reaches a barrier (also called a sync point), until the last thread reaches the barrier. All threads that are blocked by the barrier will continue to execute.

This article describes the following points in the Cyclicbarrier synchronization tool class

    1. Through the case analysis
    2. Two different kinds of constructor tests
    3. The difference between Cyclicbarrier and Countdownlatch
    4. Await method and source code analysis.
Demand

Following the previous CountDownLatch simulation game loading, now that the user clicks the Start button, it is necessary to match five players including themselves to start the game, and match the player's success into the select role stage. When the 5-player character is selected, the game starts to enter. Enter the game need to load the relevant data, until all players are loaded after the official start of the game.

Solution Solutions

From the requirements to know, want to start the game need to go through three stages, respectively is

    1. Match players
    2. Select role
    3. Loading data

In these three phases, you need to wait for each other to complete before you can continue into the next phase.
This can be used CyclicBarrier as a node for each stage, waiting for other players to arrive at the next stage.

Defining classes that inherit runnable

Here the name is called StartGame , contains two attributes

private String player;private CyclicBarrier barrier;

Initialize two properties by constructor function

public StartGame(String player, CyclicBarrier barrier) {    this.player = player;    this.barrier = barrier;}

The Run method is as follows

public void run() {    try {        System.out.println(this.getPlayer()+" 开始匹配玩家...");        findOtherPlayer();        barrier.await();        System.out.println(this.getPlayer()+" 进行选择角色...");        choiceRole();        System.out.println(this.getPlayer()+" 角色选择完毕等待其他玩家...");        barrier.await();        System.out.println(this.getPlayer()+" 开始游戏,进行游戏加载...");        loading();        System.out.println(this.getPlayer()+" 游戏加载完毕等待其他玩家加载完成...");        barrier.await();        start();    } catch (Exception e){        e.printStackTrace();    }}

Other methods Findotherplayer (), choicerole () wait for use

Thread.sleep()

To simulate the time spent

Writing test Code

Cyclicbarrier has two constructors, as follows

public CyclicBarrier(int parties) {}public CyclicBarrier(int parties, Runnable barrierAction) {}

Let's take a look at the constructor of a parameter

Cyclicbarrier (int parties)
public static void main(String[] args) throws IOException {    CyclicBarrier barrier = new CyclicBarrier(5);    Thread player1 = new Thread(new StartGame("1",barrier));    Thread player2 = new Thread(new StartGame("2",barrier));    Thread player3 = new Thread(new StartGame("3",barrier));    Thread player4 = new Thread(new StartGame("4",barrier));    Thread player5 = new Thread(new StartGame("5",barrier));    player1.start();    player2.start();    player3.start();    player4.start();    player5.start();    System.in.read();}

The test results are as follows

Cyclicbarrier (int parties, Runnable barrieraction)
CyclicBarrier barrier = new CyclicBarrier(5);

Replaced by

CyclicBarrier barrier = new CyclicBarrier(5, () -> {    try {        System.out.println("阶段完成,等待2秒...");        Thread.sleep(2000);        System.out.println("进入下个阶段...");    } catch (InterruptedException e) {        e.printStackTrace();    }});

And look at the effect.

You can see that the Runnable object that is passed in when instantiating Cyclicbarrier is executed when a node is reached. And every time it arrives, it executes once.

The difference between Cyclicbarrier and Countdownlatch
Countdownlatch Cyclicbarrier
The count is 0 o'clock and cannot be reset When the count reaches 0, the count is reset to the incoming value to start again
Call the countdown () method Count minus one, call the await () method to block only, and have no effect on the count Call the await () method count minus one, and if the value after minus one is not equal to 0, the thread blocks
No re-use can be reused
Await method
public int await(){}public int await(long timeout, TimeUnit unit){}

The no-reference await method is not introduced here, mainly introduces the following await method.
A parameter await method passes two parameters, one is time, the other is the time unit
The following two exceptions occur when calling an await method with a parameter

java.util.concurrent.TimeoutExceptionjava.util.concurrent.BrokenBarrierException

TimeoutException exception refers to the call await method after the wait time exceeds the incoming time, the CyclicBarrier state will be changed to broken, the other calling method will await throw brokenbarrierexception exception, when the CyclicBarrierwill become unavailable, the reset() state of the method reset needs to be called CyclicBarrier .

Why do you say that?
Source analysis A wave can be seen.
The await method, whether it is an argument or a non-argument, is called, and CyclicBarrier dowait(boolean timed, long nanos) The method code is too long, and the interception section is posted.

private int dowait(boolean timed, long nanos){    //加锁、try catch代码    final Generation g = generation;    //判断栅栏的状态    if (g.broken)        throw new BrokenBarrierException();    //...省略    int index = --count;    //(index == 0) 时的代码,省略    for (;;) {        try {            if (!timed)                trip.await();            else if (nanos > 0L)                nanos = trip.awaitNanos(nanos);        } catch (InterruptedException ie) {}        //判断栅栏的状态        if (g.broken)            throw new BrokenBarrierException();        if (g != generation)            return index;        //判断是否是定时的,且已经超时了        if (timed && nanos <= 0L) {            //打破栅栏的状态            breakBarrier();            throw new TimeoutException();        }    }    //解锁}

At the end of the code to determine whether the current wait has timed out, if it is called the breakBarrier() method, and throws the TimeoutException exception, the following is breakBarrier() the code

private void breakBarrier() {    generation.broken = true;    count = parties;    trip.signalAll();}

The broken state is set to true in the code, which means that the current fence removes the damaged state, resets the number of fences, and then wakes up other waiting threads. When the awakened thread or other thread enters the Dowait method, the Brokenbarrierexception exception is thrown

Case source code Address: Github.com/rainbowda/learnway/tree/master/learnconcurrency/src/main/java/com/learnconcurrency/utils/cyclicbarrier

Feel good about a star, thank you.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.