zoukankan      html  css  js  c++  java
  • Java中CountDownLatch和CyclicBarrier

    Java编程思想中的例子
    import
    javax.validation.constraints.Size; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; class TaskPortion implements Runnable{ private static int count; private final int id=count++; private final CountDownLatch latch; private static Random random=new Random(47); public TaskPortion(CountDownLatch latch) { this.latch = latch; } public void run() { try { doWork(); } catch (InterruptedException e) { e.printStackTrace(); } latch.countDown(); } public void doWork() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(random.nextInt(1000)); System.out.println(this+"complete"); } @Override public String toString() { return "TaskPortion: "+String.format("%1$-2d",id); } } class WaitingTask implements Runnable{ private final CountDownLatch latch; private static int count; private final int id=count++; public WaitingTask(CountDownLatch latch) { this.latch = latch; } public void run() { try { latch.await(); System.out.println(this); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public String toString() { return "waiting task pass"+String.format("%1$-2d",id); } } public class CountDownLatchDemo { private static final int SIZE=20; public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); CountDownLatch latch=new CountDownLatch(SIZE); for (int i=0;i<SIZE;i++) executorService.execute(new TaskPortion(latch)); // for (int i = 0; i < SIZE; i++) { executorService.execute(new WaitingTask(latch));
         executorService.shutdown();
        } 
      }
    }

    countdownlatch中有个计数器,当计数器减少到0的时候,释放所有等待的线程,coutDown()会让计数器的值减少,调用await()的线程将会进入等待状态,直到调用countdownlatch使得计数器数值减少到0,所有等待的线程都会开始执行。

    CyclicBarrier

    这个相对于上面的countdownlatch来说,这种可以重复的使用,而且await()已经具备countdownlatch中的countdown()和await()两种方法的作用。(前者await()被线程调用一次计数减一,后者不会,只能通过countdown())

    首先了解他的构造方法。

    方法

     自己独立敲了一段书上的模拟赛马的demo(来自于Java编程思想)

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.*;
    
    class Horse implements Runnable{
        private CyclicBarrier barrier;               //ByclicBarrier用来控制本类的在释放屏障之前的动作,由构造函数传入
        private int stride=0;               //马跑得轨迹
        private static int count;             //马的数量
        private final int id=count++;          //设置马的id
        private Random random = new Random(47);    //模拟赛马
        
        public Horse(CyclicBarrier barrier) {
            this.barrier = barrier;
        }
        @Override
        public void run() {
           try{
               while(!Thread.interrupted()){            //这里模拟赛马的过程
                   TimeUnit.MILLISECONDS.sleep(500);
                barrier.await();
                stride+=random.nextInt(3);
               }
           }catch(Exception e){
               e.printStackTrace();
            }
        }
        @Override
        public String toString() {
            return "Horse "+id+" ";
        }
        public String  getTrack(){
            StringBuilder s=new StringBuilder();//返回马当前到达屏障之后走的路径
            for (int i = 0; i < stride; i++) {
                s.append("=");
            }
            return s.toString();
        }
        public int getStride() {
            return stride;                    //马走了多少
        }
    
        public int getId() {
            return id;
        }
    }
    class HorseRace {
        private int nhorse;
        private ExecutorService exec;
        private final int FINISH_LINE = 75;
        private CyclicBarrier barrier;
        List<Horse> horses = new ArrayList<Horse>();
        private String track;
    public HorseRace(int nhorse, ExecutorService executorService) { exec = executorService; this.nhorse = nhorse; StringBuilder s = new StringBuilder(); for (int i = 0; i < FINISH_LINE; i++) { s.append("="); } track = s.toString(); System.out.println(s.toString()); barrier = new CyclicBarrier(nhorse, () -> { //表达式中定义了释放屏障之前的动作,打印当前所有马的路程并且判断是否有的码已经到达终点 System.out.println(track); for (Horse horse : horses) { System.out.println(horse.getTrack()); if (horse.getStride() > FINISH_LINE) { System.out.println(horse.getId() + " won"); exec.shutdownNow(); return; } } }); for (int i = 0; i < nhorse; i++) { Horse horse = new Horse(barrier); exec.execute(horse); horses.add(horse); } } } public class HorseRaceDeno { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); new HorseRace(7, executorService); } }

     两者区别总结:

    CyclicBarrier:是可以重重复使用的,只有等待线程积累到一定的数量的时候才会释放屏障,在释放屏障的时候还可以使用接口初始化CyclicBarrier变量(在里面定义释放屏障之前的动作,可以是释放线程池,终止上面所说的线程)。也可以使用只有int数据类型创建CyclicBarrier变量,这样只有在释放屏障的时候没有多余的动作。

    CountDownLatch:含有两个重要的方法CountDown()和await(),前者调用一次,CountDownLatch对象就会计数减少一次。await()导致当前线程等待计数器减少到零为止,除非出现中断的情况,而且CountDownLatch只有一次的机会,只会阻塞线程一次。

    触发屏障的事件不同:前者只有足够的线程调用await时候才会触发线程,后者是计数器减少到零的时候才会触发屏障,但是导致计数器减少的可能只是一个线程。

  • 相关阅读:
    testng
    RF相关命令
    批处理bat相关
    VIM常用快捷键
    JAVA异常处理
    cucumber+selenium
    webDriver各版本对应
    python源码
    python之logging模块
    pywinauto进阶练习
  • 原文地址:https://www.cnblogs.com/feixiangdecainiao/p/10451369.html
Copyright © 2011-2022 走看看