[] --- CyclicBarrier concurrent programming principles Introduction Use +

Source Address: https://github.com/nieandsun/concurrent-study.git


Principle 1 Introduction

CyclicBarrier, Chinese translation is 循环屏障the meaning of its name we can at least know two things:

  • It can be recycled
  • It is a barrier

1.1 CyclicBarrier principle barrier

1.1.1 await null reference

The principle is as follows

  • (1) For example, we make CyclicBarrier intercepted three threads (Using the default constructor CyclicBarrier (int parties)), Three threads may be blocked at the same time open, it may not simultaneously turned on, as shown below:

Here Insert Picture Description

  • (2) If the threads 1 and 3 have reached the thread await point (or a barrier point) of each set, but not to the thread 2, they will wait for the thread 2, as shown below:

Here Insert Picture Description

  • (3/1) until the thread 2 also await the arrival point, and then again three threads to run simultaneously seize

Here Insert Picture Description

  • (3/2) CyclicBarrier fact that there are more cattle, it can not only select the number intercepted threads, you can also add a barrierAction (Call the constructor CyclicBarrier (int parties, Runnable barrierAction)). And after the execution timing of this is the thread barrierAction await 1,2,3 have reached the point, that we here can do a lot of interesting things. If the barrierAction, FIG above can be changed following:

Here Insert Picture Description


When the time passed parameters 1.1.2 await

Drawing here is not, in fact, the CyclicBarrier await method can also pass a time, for example, thread 2 await incoming waiting time of 2 seconds, two seconds after the other thread if not reached await point, it himself first run, and throws an exception. .


The 1.2 CyclicBarrier cycle What does it mean

1.1 is really just talked about the principle CyclicBarrier barrier, but why it is called the circulation barrier it? ? ?
In fact, this is, who saw the underlying source CountDownLatch know whether or CyclicBarrier they control the number of threads in fact depend on a state变量.

  • For example, I was in CountDownLatch specifies the initial state of the number 5, then once countDown, my state decreased by one, until the state was reduced to 0, await automatically release - "But in this state in CountDownLatch Once initialized, you can only reduce, reuse can not be re-used.
  • But if I was in CyclicBarrier also specify the initial state of the number 5, for example, I have 10 threads, it will first be blocked for the first five thread -> When they have reached the point await -> Run seize; then you do not need the number manually reset state, a CyclicBarrier after five threads will automatically perform the same operation 这就是所谓的循环的意思.

2 CountDownLatch relatively simple and CyclicBarrier

Read my last article, " [Concurrent Programming] - CountDownLatch Principle Introduction + to use " 2.3 Summary of look here, will certainly feel CyclicBarrier and achieve CountDownLatch of 发令枪usage like ah.

In fact, really like, but there are some differences:

  • First, CountDownLatch actually made a thread to block other threads, so that other threads to achieve synchronization at a certain point; and CyclicBarrier is
    thus blocked by their own individual worker himself calls await, until all worker threads reaches the specified barrier, then everyone down together go.
  • Secondly, CountDownLatch counter (state) can only be used once, and CyclicBarrier counter can be used repeatedly.
  • There, CyclicBarrier of barrierAction actually provides more operational space for us
  • Finally, the use of terms
    • I CyclicBarrier equivalent to the number specified state is 3, that is, after three threads to reach the barrier point, three threads together through this barrier continues to point to seize the run;
    • And I CountDownLatch 3 specifies the number of state, I do not care you are a few threads, you just give me countDown three times, you can cross the barrier point I had set up.

3 specific use


3.1 demo1 - awit not passed in time, after a specified number of threads to reach the barrier point, and then together to seize the run (cycle interception)

  • code
package com.nrsc.ch2.juctools;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class CyclicBarrierDemo1 {

    private final static int threadCount = 6;
    static CyclicBarrier barrier = new CyclicBarrier(2);

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

        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;

            //这里故意让后续线程晚一秒开启
            Thread.sleep(1000);
            exec.execute(() -> test(threadNum));
        }
        exec.shutdown();

    }

    private static void test(int threadNum) {
        try {
            log.info("线程{}已经准备就绪!", threadNum);
            barrier.await();
        } catch (InterruptedException e) {
            log.error("InterruptedException", e);
        } catch (BrokenBarrierException e) {
            log.error("BrokenBarrierException", e);
        }
        log.info("线程{}继续运行!", threadNum);
    }
}
  • Test Results:

Here Insert Picture Description


3.2 demo2 - await incoming time t, in front of the thread reaches the barrier at this point and wait, after more than time t thrown across the barrier continues to run

package com.nrsc.ch2.juctools;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class CyclicBarrierDemo2 {
    private final static int threadCount = 2;
    static CyclicBarrier barrier = new CyclicBarrier(2);

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

        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            //这里故意让后续线程晚一秒开启
            Thread.sleep(2000);
            exec.execute(() -> test(threadNum));
        }
        exec.shutdown();

    }

    private static void test(int threadNum) {
        try {
            log.info("线程{}已经准备就绪!", threadNum);
            barrier.await(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("InterruptedException", e);
        } catch (BrokenBarrierException e) {
            log.error("BrokenBarrierException", e);
        } catch (TimeoutException e) {
            log.error("TimeoutException", e);
        }

        log.info("线程{}继续运行!", threadNum);
    }
}
  • Test Results

Here Insert Picture Description


Some information for each thread running in front after use barrierAction reach statistical barrier - 3.3 demo3

  • code
package com.nrsc.ch2.juctools;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.*;

@Slf4j
public class CyclicBarrierDemo3 {
    private final static int threadCount = 5;
    
    private static Map<String, Integer> concurrentHashMap = new ConcurrentHashMap();

    static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
        MapUtils.verbosePrint(System.out, "前几个线程准备的数据", concurrentHashMap);
    });

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

        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;

            //这里故意让后续线程晚一秒开启
            Thread.sleep(1000);
            exec.execute(() -> test(threadNum));
        }
        exec.shutdown();

    }

    private static void test(int threadNum) {
        try {

            //模拟进行部分准备工作,并将准备的结果放入到Map容器
            int random = new Random().nextInt(10);
            log.info("线程{}准备的数据-{}",Thread.currentThread().getName(),random);
            concurrentHashMap.put(Thread.currentThread().getName(), random);

            log.info("线程{}已经准备就绪!", threadNum);
            barrier.await();

        } catch (InterruptedException e) {
            log.error("InterruptedException", e);
        } catch (BrokenBarrierException e) {
            log.error("BrokenBarrierException", e);
        }

        log.info("线程{}继续运行!", threadNum);
    }
}
  • Test Results

Here Insert Picture Description

Published 218 original articles · won praise 295 · views 500 000 +

Guess you like

Origin blog.csdn.net/nrsc272420199/article/details/105109937