天天看點

CyclicBarrier,線程屏障

CyclicBarrier

使用場景

特點

  1. CyclicBarrier:讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續工作。CyclicBarrier 預設的構造方法是 CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每個線程調用 await 方法告訴 CyclicBarrier 目前線程已經到達了屏障,然後目前線程被阻塞。

code

import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CyclicBarrierDemo {

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

        ExecutorService executor = Executors.newCachedThreadPool();

        // 定義了一組屏障
        int parties = 5;
        CyclicBarrier barrier = new CyclicBarrier(parties, () -> {
            log.info("線程組全部到達屏障前,會優先執行這裡,callback is running");
        });

        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(barrier, threadNum);
//                    raceWithTime(barrier, threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        executor.shutdown();
    }

    private static void race(CyclicBarrier barrier, int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        // 在這裡阻塞,等待組内所有的線程都執行完,來到屏障前,再一起continue執行
        barrier.await();
        log.info("{} 各個線程等待再一起繼續工作 continue", threadNum);
    }

    /**
     * 帶逾時時間,過了給定時間則不等待
     *
     * @param barrier
     * @param threadNum
     * @throws Exception
     */
    private static void raceWithTime(CyclicBarrier barrier, int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        try {
            // 帶逾時時間,過了給定時間則不等待
            barrier.await(2000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.warn("BarrierException", e);
        }
        log.info("{} continue", threadNum);
    }
}