您的位置:首页 > 其它

CyclicBarrier与CountDownLatch使用

2018-08-13 19:17 99 查看

首先查看CyclicBarrier的类图

 

发现CyclicBarrier并没有超类和实现接口,因此CyclicBarrier只是一个工具类,用以协调线程运行;

与之类似 CountDownLatch也是一个工具类,下面列举了其主要方法

至于两者,对CyclicBarrier比较在意其await方法,而CountDownLatch则比较在意其await与countDown方法

一个简单的小实例:

[code]import java.util.concurrent.*;

public class Main{
public static void main(String[] args) {
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("当前5个阶段结束");
}
};
CyclicBarrier barrier=new CyclicBarrier(3,runnable);
CountDownLatch latch=new CountDownLatch(3);

for(int i=0;i<3;i++){
MyThread thread=new MyThread(barrier,latch);
thread.start();
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("执行完成");
}
}
static class MyThread extends Thread{
private final CyclicBarrier barrier;
private final CountDownLatch latch;
//当前每个线程均有5个阶段
private static int PHASE=5;

MyThread(CyclicBarrier barrier,CountDownLatch latch) {
this.barrier = barrier;
this.latch=latch;
}

@Override
public void run() {
for(int phase=0;phase<PHASE;phase++){
try {
doPhase(phase);
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
latch.countDown();

}
protected void doPhase(int phase) throws InterruptedException {
System.out.println("当前线程"+this.getName()+"正在执行第"+phase+"阶段");
Thread.sleep(1000);
System.out.println("当前线程"+this.getName()+"已结束第"+phase+"阶段");
}
}
}

输出:

当前线程Thread-0正在执行第0阶段
当前线程Thread-2正在执行第0阶段
当前线程Thread-1正在执行第0阶段
当前线程Thread-0已结束第0阶段
当前线程Thread-1已结束第0阶段
当前线程Thread-2已结束第0阶段
当前5个阶段结束
当前线程Thread-0正在执行第1阶段
当前线程Thread-1正在执行第1阶段
当前线程Thread-2正在执行第1阶段
当前线程Thread-2已结束第1阶段
当前线程Thread-0已结束第1阶段
当前线程Thread-1已结束第1阶段
当前5个阶段结束
当前线程Thread-1正在执行第2阶段
当前线程Thread-0正在执行第2阶段
当前线程Thread-2正在执行第2阶段
当前线程Thread-1已结束第2阶段
当前线程Thread-0已结束第2阶段
当前线程Thread-2已结束第2阶段
当前5个阶段结束
当前线程Thread-2正在执行第3阶段
当前线程Thread-1正在执行第3阶段
当前线程Thread-0正在执行第3阶段
当前线程Thread-0已结束第3阶段
当前线程Thread-1已结束第3阶段
当前线程Thread-2已结束第3阶段
当前5个阶段结束
当前线程Thread-2正在执行第4阶段
当前线程Thread-0正在执行第4阶段
当前线程Thread-1正在执行第4阶段
当前线程Thread-1已结束第4阶段
当前线程Thread-0已结束第4阶段
当前线程Thread-2已结束第4阶段
当前5个阶段结束
执行完成
 

分析:

CyclicBarrier的用途是创建一个栅栏(从其名字中的Barrier可以看出),构造函数为

[code]CyclicBarrier(int parties, Runnable barrierAction)

意思是在线程A调用它(CyclicBarrier)的await方法后,线程A将会阻塞在这里。直到同一个barrier上的线程调用其await方法达到预先构造函数中int值的次数,所有在此处的线程阻塞将会结束,如果barrierAction不为null,在阻塞结束后将调用该barrierAction的run方法。由其名字中的Cyclic可以看出该类是可重用的,当await的阻塞解除后再次调用await将会再次堵塞;

[code]CountDownLatch

称之为闭锁(严格来说这并不是闭锁,只是闭锁的一种实现罢了,但长久以来大家都这么叫了),

其构造函数

[code]CountDownLatch(int count)

说明在某线程调用其await方法后会阻塞,须经其countDown方法调用count次后,阻塞解除,进而继续执行

由于这两者的特性,往往CyclicBarrier常用来实现带有阶段性质的操作或者需要实现某种协议,比如几个家庭决定在6点在麦当劳集合等等,CountDownLatch用以实现确保某些活动知道其他活动都完成后才继续进行,相较两者而言,一些操作使用两者都能实现,因此过于区分两者含义是不正当的;以我而言,两者只存在语义上的差异,功能上一个具有阻塞结束后的操作而另一个没有罢了(实现此操作并不困难);

另外对于InterruptionException这个异常的捕获也很有技巧;

InterruptedException

是一个受检异常,需要显式抛出或者强制处理,当某个方法抛出该异常时,如果你不知道如何处理,请仍旧抛出,如果抛出此异常担心会污染已设计好的接口,请将其装饰为非受检异常(如

IllegalStateException

)再抛出,并给以文档说明;

如下:

try{
//操作 可能抛出InterruptedException
}catch(InterruptedException e){
if(knowHowToHandle()){
handleException();
}else if(DoWantTointerface()){
throw new RuntimeException(e);
}
else {
otherOperations();
}
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: