版权声明:未经允许禁止转载 https://blog.csdn.net/weixin_38481963/article/details/88070679
CyclicBarrier适用于这样的情况:你希望创建一组任务,他们并行的执行工作,然后在进行下一个步骤之前等待,直到所有的任务都完成。这非常像CountDownLatch,只是CountDownLatch是只触发一次的事件,而CyclicBarrier可以多次重用。
CyclicBarrier用途有两个:
- 让一组线程等待至某个状态后再同时执行。
- 让一组线程等待至某个状态后,执行指定的任务。
这两个特点对应着CyclicBarrier的两个构造函数。
//第一个构造函数
public CyclicBarrier(int parties) {...}
//第二个构造函数
public CyclicBarrier(int parties, Runnable barrierAction) {...}
之后针对这两个特性,分别编写样例测试。
1、让一组线程等待至某个状态后再同时执行
例如:小明、小刚和小华约定好了,放学后在校门口集合,一起回家。
用CyclicBarrier模拟就是:
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class GoHome implements Runnable{
private String name;
private final CyclicBarrier barrier;
public GoHome(String name, CyclicBarrier barrier){
this.name = name;
this.barrier = barrier;
}
public void run(){
try{
System.out.println(name + "出发");
TimeUnit.MILLISECONDS.sleep(500); //模拟每个人到达学校门口的时间
System.out.println(name + "到达学校门口");
barrier.await();
System.out.println("所有人到齐,一起回家");
}catch(InterruptedException e){
e.printStackTrace();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
}
}
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3);
String names[] = {"小明","小刚","小华"};
ExecutorService exe = Executors.newCachedThreadPool();
for(int i=0; i< names.length; i++)
{
exe.execute(new GoHome(names[i],barrier));
}
exe.shutdown();
}
}
结果:
小明出发
小刚出发
小华出发
小刚到达学校门口
小明到达学校门口
小华到达学校门口
所有人到齐,一起回家
所有人到齐,一起回家
所有人到齐,一起回家
你还可以尝试注释掉barrier.await();
,看一下结果如何。
CyclicBarrie是可以重用的:
你可以在Main函数中追加,以下代码,了解CyclicBarrie的复用特性:
try{
TimeUnit.MILLISECONDS.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
//又来了三个人
String others[] = {"Tom","Jerry","Marry"};
for(int i=0; i<3; i++)
{
new Thread(new GoHome(others[i],barrier)).start();
}
2、让一组线程等待至某个状态后,执行指定的任务。
这里要注意的是,驱动指定任务的线程,是利用上面的线程中一个来执行的,并没有启动新的线程。
我们改一下上面那个场景:小明、小刚和小华约定好了,放学后在餐厅门口集合,一起去吃饭。
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class GoHome implements Runnable{
private String name;
private final CyclicBarrier barrier;
public GoHome(String name, CyclicBarrier barrier){
this.name = name;
this.barrier = barrier;
}
public void run(){
try{
System.out.println(Thread.currentThread().getName() + " : " + name + "出发");
TimeUnit.MILLISECONDS.sleep(500); //模拟每个人到达学校门口的时间
System.out.println(Thread.currentThread().getName() + " : " + name + "到达餐厅门口");
barrier.await();
}catch(InterruptedException e){
e.printStackTrace();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
}
}
class EatLunch implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName() + " : " + "大家一起去打饭");
}
}
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3,new EatLunch());
String names[] = {"小明","小刚","小华"};
ExecutorService exe = Executors.newCachedThreadPool();
for(int i=0; i< names.length; i++)
{
exe.execute(new GoHome(names[i],barrier));
}
exe.shutdown();
}
}
结果:
pool-1-thread-1 : 小明出发
pool-1-thread-2 : 小刚出发
pool-1-thread-3 : 小华出发
pool-1-thread-1 : 小明到达餐厅门口
pool-1-thread-2 : 小刚到达餐厅门口
pool-1-thread-3 : 小华到达餐厅门口
pool-1-thread-3 : 大家一起去打饭