当前位置: 首页 > Thinking in Java > 正文

第21章 – 并发 – 新类库中构件 – CyclicBarrier

第21章 – 并发 – 新类库中构件 – CyclicBarrier

  1. CyclicBarrie 简介

CyclicBarrier 初始化时可以传入构造器两个参数,一个int型的 parties表示参与者(线程)的数量.

另一个是一个Runnable,表示所有参与者重新执行之前要执行的任务.

参与者线程中调用CyclicBarrier的await()使得调用该方法的线程开始等待,

当因为调用CyclicBarrier的await()而等待的线程数达parties时,所有await()的线程将被重新唤醒,

在这些线程唤醒并重新运行之前,可以执行CyclicBarrier构造函数中传入的Runnable.

当然,也可以将Runnable指定为null,则在所有await的线程被重新唤醒重新执行之前不执行任何操作,

这个也相当与使用了另外一个只有int型的parties的构造函数.

两个构造函数为:

CyclicBarrier(int parties)

CyclicBarrier(int parties, Runnable barrierAction)

这个类与CountDownLatch不同的是,CountDownLatch需要手工调用CountDown,然后内部计数减1,

当内部计数为0时,所有await()的线程被唤醒并重新执行.

并且CountDownLatch 只能使用一次,即CountDown计数变成0之后,这个CountDownLatch就不再起作用了.

而调用CyclicBarrier的await()时,相当与自动调用了countDown.因此指定数量的线程都调用了await()

之后,相当与CountDown内部计数为0了,此时在CyclicBarrier上等待的线程被唤醒重新执行.

同时,CyclicBarrier可以重新使用,即上述线程重新执行之后,仍然可以再次调用CyclicBarrier的await()

让线程等待,已经被唤醒的所有线程再次同时处于await状态时,又可以再次调用构造函数中的Runnable,

然后所有在CyclicBarrier上await()的线程重新唤醒执行,如此反复….

当执行需要终结时,可以在构造函数的Runnable中设置一个终结条件,在指定数量的线程的run中

使用while(!终结条件)来进行循环执行,当终结调节满足时,循环退出,指定数量的线程结束执行.

  1. 典型用法(P724中赛马游戏)

创建CyclicBarrier时,传入参与者马的个数,和处理马每跑一步之后的状态的Runnable.

马跑一步(马线程执行了一次,即,执行了run中一个while循环)就暂停一次,

等待CyclicBarrier的Runnable来处理当前所有马的状态

代码:

package concurrency;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;

    class Horse implements Runnable
    {
      private static int counter = 0;
      private final int id = counter++;
      private int strides = 0;
      private static Random rand = new Random(47);
      private static CyclicBarrier barrier;

      public Horse(CyclicBarrier b)
      {
        barrier = b;
      }

      public synchronized  int getStrides()
      {
        return strides;
      }

      @Override
      public void run()
      {
        try
        {
          while(!Thread.interrupted())
          {
            synchronized (this)
            {
              //模拟马跑一步的长度,能是0,1,2
              strides += rand.nextInt(3);//生成0,1或2
            }
            barrier.await();
            //马跑一步就暂停一次,等待CyclicBarrier的Runnable来处理当前所有马的状态
          }
        }
        catch (InterruptedException e)
        {
          // 可以用一种合理的方式退出
        }
        catch (BrokenBarrierException e) 
        {
          throw new RuntimeException(e);
        }
      }

      public String toString()
      {
        return "Horse " + id + " ";
      }

      public String tracks()
      {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<getstrides class="" final="" finish_line="100;" horserace="" int="" list="" private="" public="" return="" s.append="" s.tostring="" static=""> horses = new ArrayList<horse>();
      private ExecutorService exec = Executors.newCachedThreadPool();
      private CyclicBarrier barrier;

      public HorseRace(int nHorses,final int pause)
      {
        //创建CyclicBarrier,传入参与者马的个数,
        //和处理马每跑一步之后的状态的Runnable
        barrier = new CyclicBarrier(nHorses,new Runnable()
        {
          //执行这个run之前,所有马线程都处于await()状态
          public void run()
          {
            StringBuilder s = new StringBuilder();

            for(int i=0;i<finish_line for="" horse:horses="" if="" s.append="" system.out.println="">= FINISH_LINE)
              {
                System.out.println(horse + " won!");
                exec.shutdownNow();
                return;
              }
            }

            try
            {
              TimeUnit.MILLISECONDS.sleep(pause); //这里指定马两次跑之间的间隔时间
            }
            catch (InterruptedException e)
            {
              System.out.println("barrier-action sleep interrupted");
            }

          }
        });

        for(int i=0;i<nhorses args="" exec.execute="" horse="" horses.add="" if="" int="" main="" nhorses="10;" pause="20;" public="" static="" void="">0)
        {
          int n = new Integer(args[0]);
          nHorses = n>0 ? n:nHorses;
        }

        if(args.length >1)
        {
          int p = new Integer(args[1]);
          pause = p > -1 ? p : pause;
        }

        new HorseRace(nHorses,pause);

      }
    }</nhorses></finish_line></horse></getstrides>

执行的结果,类似下面这样(部分省略):

……省略部分

====================================================================================================

*****0

*****1

*****2

*****3

*****4

***5

**6

****7

****8

*****9

====================================================================================================

*****0

**1

***2

***3

***4

***5

****6

****7

****8

*****9

====================================================================================================

*****0

****1

*****2

***3

*****4

***5

**6

*****7

**8

*****9

Horse 1 won!

赞 赏

   微信赞赏  支付宝赞赏


本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2134.html | 边城网事

该日志由 边城网事 于2015年03月18日发表在 Thinking in Java 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 第21章 – 并发 – 新类库中构件 – CyclicBarrier | 边城网事
关键字: ,

第21章 – 并发 – 新类库中构件 – CyclicBarrier 暂无评论

发表评论

快捷键:Ctrl+Enter