zoukankan      html  css  js  c++  java
  • Java核心-多线程(7)-并发控制器-CyclicBarrier同步屏障

    1.基本概念
    中文译本同步屏障,同样来自jdk并发工具包中一个并发控制器,它的使用和CountDownLatch有点相似,能够完成某些相同并发场景,但是它们却不相同。

    2.抽象模型
    主要用来实现多个线程同步,同步后可能唤醒另外一个任务,然后继续执行线程后面的任务。CountDownLatch抽象模型却是一个或多个线程通知某个或多个线程,它没有同步功能。

    3.使用场景
    田径比赛, 虽然上一篇文章使用CountDownLatch也能实现,但是我觉得这里却使用同步屏障更简单点。

    4.CyclicBarrier使用api
    java new CyclicBarrier(int parties); //创建同步屏障,仅仅启动同步作用,中间没有需要执行的任务。
    java new CyclicBarrier(int parties, Runnable barrierAction); //创建同步屏障,不仅同步,而且中间有任务需要执行。
    java cyclicBarrier.await(); //调用一次,parties就会减1,直到变为0时,执行barrierAction任务后(配置情况下),然后执行此代码的线程才能停止阻塞,继续执行。
    java ps:因为使用CyclicBarrier的线程都会阻塞在await方法上,所以在线程池中使用CyclicBarrier时要特别小心,如果线程池的线程过少,那么就会发生死锁了。

    5.使用示例(田径比赛)

        public static void main(String[] args) {
    		ExecutorService executor = Executors.newFixedThreadPool(3);
    		final CyclicBarrier startBarrier = new CyclicBarrier(3, new Runnable() {
    			@Override
    			public void run() {
    				
    				try {
    					System.out.println("他们都准备好了,那就开跑吧");
    					System.out.println("3");
    					Thread.sleep(1000);
    					System.out.println("2");
    					Thread.sleep(1000);
    					System.out.println("1");
    					Thread.sleep(1000);
    					System.out.println("0");
    					System.out.println("go!!!");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		});
    		CyclicBarrier endBarrier = new CyclicBarrier(3, new Runnable() {
    			@Override
    			public void run() {
    				System.out.println("都到达了终点,比赛结束");
    			}
    		});
    		for(int i=3;i>0;i--){
    			final int num = i;
    			Runnable runnable = new Runnable() {
    				
    				@Override
    				public void run() {
    					try {
    						int time = (int)(Math.random()*1000);
    						Thread.sleep(time);
    						System.out.println("运动员" + num + "号,准备了" + time + "ms,准备结束!");
    						startBarrier.await();
    						System.out.println("运动员" + num + "号,开始跑了");
    						int runtime = (int)(Math.random()*10000);
    						Thread.sleep(runtime);
    						System.out.println("运动员" + num + "号,用时:" + runtime + "ms");
    						endBarrier.await();
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    			};
    			executor.submit(runnable);
    		}
    	}
    

    执行结果

    运动员1号,准备了580ms,准备结束!
    运动员3号,准备了866ms,准备结束!
    运动员2号,准备了878ms,准备结束!
    他们都准备好了,那就开跑吧
    3
    2
    1
    0
    go!!!
    运动员2号,开始跑了
    运动员1号,开始跑了
    运动员3号,开始跑了
    运动员2号,用时:2008ms
    运动员3号,用时:5587ms
    运动员1号,用时:6634ms
    都到达了终点,比赛结束
    

    6.和CountDownLatch的区别
    <1>CountDownLatch能唤醒多个线程,而CyclicBarrier只能唤醒一个线程;
    <2>一个线程或多个线程(A)使用CountDownLatch通知另外一个或多个线程(B),A线程之间不会有同步功能,需要多个latch才能实现同步功能;而CyclicBarrier能同步A线程组的执行步骤;
    <3>CountDownLatch是一次性的,不能重置,而CyclicBarrier不是,它有reset()方法;

  • 相关阅读:
    算法题---最长公共前缀
    算法练习题---罗马数字转int
    算法练习题---原地删除数组元素
    获取当前服务的IP和端口号
    算法练习题---回文数
    Java数学表示式解析工具- jeval
    Redis的安装与部署
    Centos开机自启动redis
    Java 7 的 7 个新的 “酷” 特性
    java7新特性——使用ThreadLocalRandom产生并发随机数
  • 原文地址:https://www.cnblogs.com/leeethan/p/10680835.html
Copyright © 2011-2022 走看看