CyclicBarrier与CountDownLatch使用

首先查看CyclicBarrier的类图

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

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

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

一个简单的小实例:

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可以看出),构造函数为

CyclicBarrier(int parties, Runnable barrierAction)

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

CountDownLatch

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

其构造函数

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();
    }
}

猜你喜欢

转载自blog.csdn.net/WK_SDU/article/details/81635040
今日推荐