CyclicBarrier与CountDownLatch功能类似,都带有计数阻塞功能。关于CountDownLatch的讲解案例
CountdownLatch阻塞主线程,等所有子线程完结了再继续下去。Syslicbarrier阻塞一组子线程,直至某个状态之后再全部同时执行(一般为子线程数量达到预期值)。并且所有线程都被释放后,还能通过reset来重用。
CyclicBarrier通过 cyclicBarrier.await(); 方法对子线程进行拦截。所以,业务逻辑在await() 前后就有两种完全不同的执行结果。
1、业务逻辑在await()之后:
package com.yc.uc.test;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @Author Allen
* @Date 2021/3/4 10:22 上午
* @Version 1.0
*/
public class CyclicBarrierDemo {
public static void main(String[] args) throws InterruptedException {
//当子线程数量加到6,执行println
CyclicBarrier cyclicBarrier = new CyclicBarrier(6, () -> {
System.out.println("所有子线程开始执行!");
});
for (int i = 0; i < 6; i++) {
int finalI = i;
new Thread(()->{
try {
Thread.sleep(1000);
//先进行await拦截子线程
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
//模拟业务逻辑
System.out.println(finalI +"执行完毕");
}).start();
}
}
}
执行结果:
所有子线程开始执行!
5执行完毕
1执行完毕
0执行完毕
2执行完毕
3执行完毕
4执行完毕
Process finished with exit code 0
上面可以看到,所有子线程创建后并没有先执行自己的业务逻辑,而是被await()拦截,当子线程数量到达期望值6后,先执行CyclicBarrier指定的println,再将所有子线程被同时放行,同时执行自己的业务逻辑。
2、业务逻辑在await()之前
package com.yc.uc.test;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @Author Allen
* @Date 2021/3/4 10:22 上午
* @Version 1.0
*/
public class CyclicBarrierDemo {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(6, () -> {
System.out.println("所有子线程执行完毕!");
});
for (int i = 0; i < 6; i++) {
int finalI = i;
new Thread(()->{
//模拟业务逻辑
System.out.println(finalI +"执行完毕");
try {
Thread.sleep(1000);
//await在业务逻辑之后
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
执行结果:
0执行完毕
1执行完毕
2执行完毕
3执行完毕
4执行完毕
5执行完毕
所有子线程执行完毕!
Process finished with exit code 0
由结果可以看出,第二次的执行结果跟上一次相比,“所有子线程执行完毕!”从最前面跑到了最后。 这是因为,子线程被创建后先执行了自己的业务逻辑,然后才被await拦截,每当await拦截一个子线程,计数加一。只有当计数累加到期望值6,才执行CyclicBarrier指定的println。