CountDownLatch和CyclicBarrier支持在java中较为简单的线程编排,通过单个线程的阻塞来获取其他异步线程的结果。
较为常见的场景为主线程阻塞来获取子线程并行计算产生结果,用于之后的运算。
两者区别:
CountDownLatch表示的是多个线程执行过程中的一种状态,状态是会发生变化的。不通时间去调用getCount()获取到的结果是不一样的,表示还有多少信号量遗留。
public class TestCountDownLunch {
public static void main(String[] args) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(2);
Thread t1 = new Thread(){
@Override
public void run() {
for(int i = 0;i<1;i++){
if(i%1000000 == 0) {
System.out.println("第一个线程" + i);
}
}
//信号量减一
countDownLatch.countDown();
}
};
Thread t2 = new Thread(){
@Override
public void run() {
for(int i = 0;i<1;i++){
if(i%990000 == 0) {
System.out.println("第二个线程" + i);
}
}
//信号量减一
countDownLatch.countDown();
}
};
t1.start();
t2.start();
//等待信号量减到0的时候,主线程继续执行(支持最长等待时间)
countDownLatch.await(10, TimeUnit.SECONDS);
for(int i = 0;i<10;i++){
System.out.println("主线程"+i);
}
}
}
CyclicBarrier表示的是多个线程执行过程中的一种状态,Barrier代表一次阻塞,状态是会发生变化的。底层使用是 ReentrantLock 和 Condition 的组合使用。
支持检查当先阻塞状态是否被打破(是否有线程被中断)isBroken(),当信号量==0、有线程超时触发异常、有线程被中断触发异常(BrokenBarrierException),都会导致阻塞被打破。
阻塞被打破之后,所有其他线程会被唤醒。
public class TestCycilcBarrier {
public static void main(String[] args) throws Exception {
//满足信号量==0的时候,自动触发回调函数
//信号量减到0之后,能够恢复到初始值2(差异点)
CyclicBarrier cyclicBarrier = new CyclicBarrier(2,() -> callBack());
for(int j = 0;j<2;j++) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100000000; i++) {
if (i % 1000000 == 0) {
System.out.println("第一个线程" + i);
}
}
try {
//信号量减一
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100000000; i++) {
if (i % 990000 == 0) {
System.out.println("第二个线程" + i);
}
}
try {
//信号量减一
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
}
static void callBack() {
System.out.println("callBack");
}
}
参考文章:https://blog.csdn.net/qq_39241239/article/details/87030142
java并发(二)--CountDownLatch|CyclicBarrier
原文:https://www.cnblogs.com/ElliottX4/p/14100481.html