首页 > 编程语言 > 详细

Java并发新构件之CounDownLatch

时间:2015-10-13 13:59:30      阅读:263      评论:0      收藏:0      [点我收藏+]

    CountDownLatch主要用于同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成。

    你可以向CountDownLatch对象设置一个初始计数值,任何在这个对象上调用wait()的方法都将阻塞,直到这个计数值达到0.其他任务在结束其工作时,可以在该对象上调用countDown()来减小这个计数值,你可以通过调用getCount()方法来获取当前的计数值。CountDownLatch被设计为只触发一次,计数值不能被重置。如果你需要能够重置计数值的版本,则可以使用CyclicBarrier。

    调用countDown()的任务在产生这个调用时并没有阻塞,只有对await()的调用会被阻塞,直到计数值到达0。

    CountDownLatch的典型用法是将一个程序分为n个互相独立的可解决人物,并创建值为0的CountDownLatch。当每个任务完成是,都会在这个锁存器上调用countDown()。等待问题被解决的任务在这个锁存器上调用await(),将它们自己锁住,直到锁存器计数结束。下面是演示这种技术的一个框架示例:

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class TaskPortion implements Runnable {
    private static int counter = 0;
    private final int id = counter++;
    private static Random random = new Random();
    private final CountDownLatch latch;
    public TaskPortion(CountDownLatch latch) {
        this.latch = latch;
    }
    @Override
    public void run() {
        try {
            doWork();
            latch.countDown();//普通任务执行完后,调用countDown()方法,减少count的值
            System.out.println(this + " completed. count=" + latch.getCount());
        } catch (InterruptedException e) {
            
        }
    }
    
    public void doWork() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));
    }
    
    @Override
    public String toString() {
        return String.format("%1$-2d ", id);
    }
}

class WaitingTask implements Runnable {
    private static int counter = 0;
    private final int id = counter++;
    private final CountDownLatch latch;
    public WaitingTask(CountDownLatch latch) {
        this.latch = latch;
    }
    @Override
    public void run() {
        try {
            //这些后续任务需要等到之前的任务都执行完成后才能执行,即count=0时
            latch.await();
            System.out.println("Latch barrier passed for " + this);
        } catch (InterruptedException e) {
            System.out.println(this + " interrupted.");
        }
    }
    
    @Override
    public String toString() {
        return String.format("WaitingTask %1$-2d ", id);
    }
}

public class CountDownLatchDemo {
    static final int SIZE = 10;
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(SIZE);
        ExecutorService exec = Executors.newCachedThreadPool();
        //10个WaitingTask
        for (int i = 0; i < 5; i++) {
            exec.execute(new WaitingTask(latch));
        }
        //100个任务,这100个任务要先执行才会执行WaitingTask
        for (int i = 0; i < SIZE; i++) {
            exec.execute(new TaskPortion(latch));
        }
        System.out.println("Launched all tasks.");
        exec.shutdown();//当所有的任务都结束时,关闭exec
    }
}

执行结果(可能的结果):

Launched all tasks.
4   completed. count=9
6   completed. count=8
3   completed. count=7
0   completed. count=6
2   completed. count=5
1   completed. count=4
5   completed. count=3
7   completed. count=2
9   completed. count=1
8   completed. count=0
Latch barrier passed for WaitingTask 0  
Latch barrier passed for WaitingTask 2  
Latch barrier passed for WaitingTask 1  
Latch barrier passed for WaitingTask 3  
Latch barrier passed for WaitingTask 4

    从结果中可以看到,所有的WaitingTask都是在所有的TaskPortion执行完成之后执行的。

    TaskPortion将随机的休眠一段时间,以模拟这部分工作的完成。而WaitingTask表示系统中必须等待的部分,它要等到问题的初始部分完成后才能执行。注意:所有任务都使用了在main()中定义的同一个CountDownLatch对象。

Java并发新构件之CounDownLatch

原文:http://my.oschina.net/itblog/blog/516282

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!