神奇好望角 The Magical Cape of Good Hope

庸人不必自扰,智者何需千虑?
posts - 26, comments - 50, trackbacks - 0, articles - 11
  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理

非主流并发工具之 CountDownLatch

Posted on 2011-10-14 14:22 蜀山兆孨龘 阅读(1704) 评论(1)  编辑  收藏 所属分类: Java SE

顾名思义,CountDownLatch 是一个用来倒计数的咚咚。如果某项任务可以拆分成若干个子任务同时进行,然后等待所有的子任务完成,可以考虑使用它。

该类的用法非常简单。首先构造一个 CountDownLatch,唯一的参数是任务数量,一旦构造完毕就不能修改。接着启动所有的子任务(线程),且每个子任务在完成自己的计算后,调用 CountDownLatch#countDown 方法将倒计数减一。最后在主线程中调用 CountDownLatch#await 方法等待计数器归零。

例如赛跑的准备阶段,八名运动员先后到达起点做好准备,然后裁判打响发令枪,准备工作就结束了,比赛开始。如果把从运动员就位到发令枪响看做赛跑准备任务,那么每个运动员的准备过程就是其子任务,可以用 CountDownLatch 模拟如下:

        final int count = 8;
        System.out.println("运动员开始就位。");

        // 构造 CountDownLatch。
        final CountDownLatch cdl = new CountDownLatch(count);
        for (int i = 1; i <= count; i++) {
            final int number = i;
            new Thread() {
                @Override
                public void run() {
                    System.out.println(number + " 号运动员到场并开始准备...");
                    try {
                        // 让运动员随机准备 2~5 秒钟。
                        TimeUnit.SECONDS.sleep(new Random().nextInt(4) + 2);
                    } catch (InterruptedException ex) {
                    }
                    System.out.println(number + " 号运动员就位。");
                    // 倒计数减一。
                    cdl.countDown();
                }
            }.start();
        }

        System.out.println("等待所有运动员就位...");
        try {
            // 等待倒计数变为 0。
            cdl.await();
            System.out.println("比赛开始。");
        } catch (InterruptedException ex) {
        }
    

运行输出(可能)为:

运动员开始就位。
1 号运动员到场并开始准备...
2 号运动员到场并开始准备...
4 号运动员到场并开始准备...
等待所有运动员就位...
8 号运动员到场并开始准备...
6 号运动员到场并开始准备...
3 号运动员到场并开始准备...
7 号运动员到场并开始准备...
5 号运动员到场并开始准备...
6 号运动员就位。
1 号运动员就位。
5 号运动员就位。
4 号运动员就位。
7 号运动员就位。
8 号运动员就位。
2 号运动员就位。
3 号运动员就位。
比赛开始。

从上面的例子还可以看出 CountDownLatch 的局限性和 CompletionService 类似,在于无法处理子任务数量不确定的情况,例如统计某个文件夹中的文件数量。另外,如果某个子任务在调用 countDown 之前就挂掉了,倒计数就永远不会归零。对于这种情况,要么用 finally 之类的手段保证 countDown 一定会被调用,要么用带参数的 await 方法指定超时时间。


评论

# re: 非主流并发工具之 CountDownLatch  回复  更多评论   

2011-10-14 20:56 by 与你同飞
谢谢,长见识了。

只有注册用户登录后才能发表评论。


网站导航: