第21章 – 并发 – 新类库中构件 – CyclicBarrier
第21章 – 并发 – 新类库中构件 – CyclicBarrier
- 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(!终结条件)来进行循环执行,当终结调节满足时,循环退出,指定数量的线程结束执行.
- 典型用法(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 | 边城网事