CyclicBarrier
使用場景
特點
- 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);
}
}