线程并发工具类-CountDownLatch与CyclicBarrier区别

首先抛个概念:

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();
              }
	}

}

猜你喜欢

转载自blog.csdn.net/tangtang1226/article/details/81480705