首先抛个概念:
CountDownLatch:一个线程等待其他线程完成工作以后再执行,相当于加强版的join,初始化的时候,给定一个数值,通过调用countDown()方法,对这个数值进行减一操作,通过调用await()方法,让当前线程等待,直到数值减到0的时候,所有await的线程开始运行。
例子:视频会议,开视频会议的人有10个人,是否开始视频会议,决定条件是:人员是否到期,换句话就是没有到的人来决定,啥时候开始视频会议,已经到了的人员,需要耐心等待,直到没有加入会议的人数为0。
CyclicBarrier:让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续执行。
例子:会议结束后,参与人员打算去聚餐,去哪里聚餐,什么时候出发,这些事情是由当前的参与者来决定,不会由组外人员来决定,而且是由所有参与人员决定,大家一起进行团体活动。
所以两者的区别:
1.CountDownLatch放行由第三方控制,CyclicBarrier放行由一组线程本身控制
2.CountDownLatch放行的条件>=线程数,CyclicBarrier放行条件=线程数
下面是视频会议CountDownLatch实现代码:
public class VideoconferenceDemo{
//会议类
public static class Videoconference implements Runnable {
//会议参加人数
private final CountDownLatch controller;
public Videoconference(int number) {
controller = new CountDownLatch(number);
}
public void arrive(String name){
System.out.printf("%s has arrived.",name);
controller.countDown();
System.out.printf("VideoConference:Waiting for %d participants.\n",controller.getCount());
}
@Override
public void run() {
System.out.printf("VideoConference:Initialization:%d participants.\n",controller.getCount());
try{
controller.await();
System.out.printf("VideoConference:All the participants have come\n");
System.out.printf("VideoConference:Let's start ...\n");
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//与会者类
public static class Participant implements Runnable {
private Videoconference conference;
private String name;
public Participant(Videoconference conference, String name) {
this.conference = conference;
this.name = name;
}
@Override
public void run() {
long duration = (long)(Math.random()*10);
try{
TimeUnit.SECONDS.sleep(duration);
}catch(InterruptedException e){
e.printStackTrace();
}
conference.arrive(name);
}
}
public static void main(String[] args) {
Videoconference conference = new Videoconference(10);
Thread threadConference = new Thread(conference);
threadConference.start();
for(int i=0;i<10;i++){
Participant p = new Participant(conference, "participant"+i);
Thread t = new Thread(p);
t.start();
}
}
}
聚餐CyclicBarrier代码:
public class CyclicBarrierDemo {
private static CyclicBarrier barrier = new CyclicBarrier(5, new Order());
private static ConcurrentHashMap<String,Long> resultMap
= new ConcurrentHashMap<>();//存放子线程工作结果的容器
//工作线程
public static class Dinner implements Runnable{
@Override
public void run() {
Long id = Thread.currentThread().getId();
resultMap.put(Thread.currentThread().getName(), id);
Random r = new Random();//随机决定工作线程的是否睡眠
try {
if(r.nextBoolean()) {
Thread.sleep(2000+id);
System.out.println("Person_"+id+" 正在考虑是否参加聚餐");
}
System.out.println("Person_"+id+" 参加中午的聚餐");
barrier.await();
Thread.sleep(1000+id);
System.out.println("Person_"+id+" 开始点菜 ");
} catch (Exception e) {
e.printStackTrace();
}
}
}
//屏蔽后处理线程
public static class Order implements Runnable{
@Override
public void run() {
StringBuilder result = new StringBuilder();
for(Map.Entry<String,Long> workResult:resultMap.entrySet()){
result.append("["+workResult.getValue()+"]");
}
System.out.println(" 到餐厅的人员有 - "+ result);
System.out.println("服务员拿来菜单");
}
}
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread(new Dinner()).start();
}
}
}