JAVA concurrent multithreading class (two): understanding and use of the synchronization barrier CyclicBarrier

Introduction

CyclicBarrier literally means a Cyclic barrier (Barrier).

What it has to do is to block a group of threads when they reach a barrier (also called a synchronization point), and the barrier will not open until the last thread reaches the barrier.

All threads intercepted by the barrier will continue to work. The default construction method of CyclicBarrier is CyclicBarrier(int parties), and its parameter indicates the number of threads intercepted by the barrier.

Each thread calls the await method to tell CyclicBarrier that I have reached the barrier, and then the current thread is blocked.

The example code is as follows:

public class CyclicBarrierTest {
    static CyclicBarrier c = new CyclicBarrier(2);
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();
                } catch (Exception e) {

                }
                System.out.println(1);
            }
        }).start();

        try {
            c.await();

        } catch (Exception e) {

        }
        System.out.println(2);
    }
}
输出
-> 2
-> 1
或者输出
-> 1
-> 2
如果把new CyclicBarrier(2)修改成new CyclicBarrier(3)则主线程和子线程会永远等待,因为没有第三个线程执行await方法,即没有第三个线程到达屏障,所以之前到达屏障的两个线程都不会继续执行。

CyclicBarrier also provides a more advanced constructor CyclicBarrier (int parties, Runnable barrierAction), which is used to execute barrierAction first when the thread reaches the barrier, which is convenient for handling more complex business scenarios.

 

code show as below:

 

public class CyclicBarrierTest2 {
    static CyclicBarrier c = new CyclicBarrier(2, new A());
    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();
                } catch (Exception e) {
                }
                System.out.println(1);
            }
        }).start();
 
        try {
            c.await();
        } catch (Exception e) {
        }
        System.out.println(2);
    }

    static class A implements Runnable {
        @Override
        public void run() {
            System.out.println(3);
        }
    }
}

=== 输出
-> 3
-> 1
-> 2

Application scenarios of CyclicBarrier

CyclicBarrier can be used to calculate data in multiple threads, and finally merge the application scenarios of calculation results. For example, we use an Excel to save all the user's bank flow, and each sheet saves each bank flow of an account in the past year. Now we need to count the user's daily bank flow, and first use multithreading to process the bank flow in each sheet. After all executions are completed, the daily average bank turnover of each sheet is obtained. Finally, the barrierAction is used to calculate the daily average bank turnover of the entire Excel using the calculation results of these threads.

 

The difference between CyclicBarrier and CountDownLatch 

The CountDownLatch counter can only be used once. The counter of CyclicBarrier can be reset using the reset() method. Therefore, CyclicBarrier can handle more complex business scenarios. For example, if an error occurs in the calculation, the counter can be reset and the threads can be executed again.

CyclicBarrier also provides other useful methods, such as getNumberWaiting method to get the number of threads blocked by CyclicBarrier. The isBroken method is used to know whether the blocked thread is interrupted. For example, the following code will return true after execution

The use code of isBroken is as follows:

import java.util.concurrent.BrokenBarrierException;

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierTest3 {

    static CyclicBarrier c = new CyclicBarrier(2);

    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();
                } catch (Exception e) {
                }
            }
        });
        thread.start();
        thread.interrupt();
        try {
            c.await();
        } catch (Exception e) {
            System.out.println(c.isBroken());
        }
    }
}


=====> 输出

 true 

 

Guess you like

Origin blog.csdn.net/bj_chengrong/article/details/108704141