pingh14

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

CountDownLatch的介绍和使用:

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达0之前,await 方法会一直受阻塞。

之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。

使用场景:

在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。

这个时候就可以使用CountDownLatch。CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。

相关实例

// 一个CountDouwnLatch实例是不能重复使用的,也就是说它是一次性的,锁一经被打开就不能再关闭使用了,如果想重复使用,请考虑使用CyclicBarrier。
public class CountDownLatchTest {
    // 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
    public static void main(String[] args) throws InterruptedException {
        // 开始的倒数锁 
        final CountDownLatch begin = new CountDownLatch(1);  
        // 结束的倒数锁 
        final CountDownLatch end = new CountDownLatch(10);  
        // 十名选手 
        final ExecutorService exec = Executors.newFixedThreadPool(10);  
        for (int index = 0; index < 10; index++) {
            final int NO = index + 1;  
            Runnable run = new Runnable() {
                public void run() {  
                    try {  
                        // 如果当前计数为零,则此方法立即返回。
                        // 等待
                        begin.await();  
                        Thread.sleep((long) (Math.random() * 10000));  
                        System.out.println("No." + NO + " arrived");  
                    } catch (InterruptedException e) {  
                    } finally {  
                        // 每个选手到达终点时,end就减一
                        end.countDown();
                    }  
                }  
            };  
            exec.submit(run);
        }  
        System.out.println("Game Start");  
        // begin减一,开始游戏
        begin.countDown();  
        // 等待end变为0,即所有选手到达终点
        end.await();  
        System.out.println("Game Over");  
        exec.shutdown();  
    }
}

 

以上实例转自:http://www.itzhai.com/the-introduction-and-use-of-a-countdownlatch.html

CyclicBarrier和CountDownLatch一样,都是关于线程的计数器。

用法略有不同,测试代码如下:

public class TestCyclicBarrier {
    private static final int THREAD_NUM = 5;    
    public static class WorkerThread implements Runnable{
        CyclicBarrier barrier;
        public WorkerThread(CyclicBarrier b){
            this.barrier = b;
        }
        public void run() {
            try{
                System.out.println("Worker's waiting");
                //线程在这里等待,直到所有线程都到达barrier。
                barrier.await();
                System.out.println("ID:"+Thread.currentThread().getId()+" Working");
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        CyclicBarrier cb = new CyclicBarrier(THREAD_NUM, new Runnable() {
            //当所有线程到达barrier时执行public void run() {
                System.out.println("Inside Barrier");
            }
        });
        for(int i=0;i<THREAD_NUM;i++){
            new Thread(new WorkerThread(cb)).start();
        }
    }

}
/*
以下是输出:
Worker's waiting
Worker's waiting
Worker's waiting
Worker's waiting
Worker's waiting
Inside Barrier
ID:12 Working
ID:8 Working
ID:11 Working
ID:9 Working
ID:10 Working
*/

 

  1.  CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。 
  2.  CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 
  3.  CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行

两者区别

http://xumingming.sinaapp.com/215/countdownlatch-vs-cyclicbarrier/

posted on 2014-01-06 00:24  pingh14  阅读(1486)  评论(2编辑  收藏  举报