ClyClicBarrier是线程并发库中的一个并发辅助类,允许一组线程相互等待,直到所有的线程都到达屏障点才被CyclicBarrier释放唤醒。释放等待线程后的CyclicBarrir可以重用,因此我们将其称之为循环的barrier。
CyclicBarrier对象的创建:
1、new CyclicBarrier(int parties):
创建具有指定数量参与者(线程)的CyclicBarrier,当所有的参与者(线程)都处于等待状态时启动屏障,但不会在启动屏障的时候执行预定义的屏障操作。
2、new CyclicBarrier(int parties, Runnable run):
创建具有指定数量参与者(线程)的CyclicBarrier,当所有的参与者(线程)都处于等待状态时启动屏障,并在启动屏障的时候执行预定义的屏障操作,预定义屏障操作是由run参数指定的,由最后一个进入等待状态的参与者(线程)执行。
CyclicBarrier中的重要方法:
int await():
在所有的参与者(线程 )中都调用了barrier的await方法之前,导致调用barrier.await方法的当前线程一直等待;即要使参与者(线程)到达 屏障点,必须在参与者(线程)中调用barrier的await方法。该方法是个阻塞方法。
CyclicBarrier的执行过程:
1、在所有的参与者(线程)中调用barrier的await方法,使当前线程到达屏障点进入等待状态。
2、CyclicBarrier在所有指定数量的参与者都进入屏障点(调用barrier的await方法)之前一直处于等待状态,等待所有的参与者(线程)都到达屏障点。
3、当指定数量的参与者(线程)都调用了barrier.await方法到达屏障点后,barrier启动屏障;如果预定义了屏障操作,则由最后一个到达屏障点的参与者(线程)执行屏障操作,也就是执行run线程。
4、参与者(线程)自调用barrier的await方法起就一直处于等待状态,当屏障操作执行完毕后,barrier会释放等待线程(参与者),并唤醒参与者,参与者(线程)又可以做自己的事情,而barrier又回到初始状态,可以被重新使用。
下面使用CyclicBarrier模拟公司员工开会的场景:
1、员工进入会议室。
2、等所有的参会员工都到达会议室后才开始会议。
3、员工在会议期间发表讲话。
/**
*
*/
package com.huaxia.concurrent.cyclicbarrier;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author wangcz
* CyclicBarrier测试入口类
* 模拟场景:公司员工开会,等全部员工都到齐后才开始会议
*/
public class CyclicBarrierTestMain {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/**假定公司参加会议的人数为20*/
CyclicBarrier cb = new CyclicBarrier(20, new BarrierThread());
Random ran = new Random();
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 1; i <= 20; i++) {
es.submit(new EmployeeJoinMeeting(cb, ran.nextInt(900) + 100));
}
es.shutdown();
}
}
/**
*
*/
package com.huaxia.concurrent.cyclicbarrier;
import java.util.concurrent.CyclicBarrier;
/**
* @author wangcz
* 前来参加会议的员工类
*/
public class EmployeeJoinMeeting implements Runnable {
private CyclicBarrier cb;
private long useTime;
/**
* @param cb
* @param useTime
*/
public EmployeeJoinMeeting(CyclicBarrier cb, long useTime) {
super();
this.cb = cb;
this.useTime = useTime;
}
/**
*
*/
public EmployeeJoinMeeting() {
super();
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
try {
/**参会员工去会议室*/
System.out.println("[" + Thread.currentThread().getName() + "] is walking to meet...");
Thread.sleep(useTime);
System.out.println("[" + Thread.currentThread().getName() + "] uses time " + useTime + "ms, now has reached meetingroom...");
/**等待所有参会员工到齐*/
cb.await();
/**参会员工发表讲话*/
System.out.println("[" + Thread.currentThread().getName() + "] has speaked in meetingroom...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
*
*/
package com.huaxia.concurrent.cyclicbarrier;
/**
* @author wnagcz
* 屏障操作线程,当最后一个线程到达屏障点,该线程执行
*/
public class BarrierThread implements Runnable {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
System.out.println("all employees has reached, now the meeting is going to begin...");
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
}
}