来自http://www.iteye.com/topic/363625
5、CountDownLatch
CountDownLatch是一个一次性的同步辅助工具,允许一个或多个线程一直等待,直到计数器值变为0。它有一个构造方法,设定计数器初始值,即在await()结束等待前需要调用多少次countDown()方法。CountDownLatch的计数器不能重置,所以说它是“一次性”的,如果需要重置计数器,可以使用CyclicBarrier。在运行环境检查的主类中,使用了CountDownLatch来等待所有验证结束,在各个并发验证的线程完成任务结束前都会调用countDown(),因为有3个并发的验证,所以将计数器设置为3。
最后将所有这些类整合起来,运行环境检查的主类如下。它会创建线程池服务和验证服务,先做一次验证(相当于是对系统做次初始化),随后并发3个验证请求。系统运行完毕会显示实际执行的节点验证次数和执行时间。如果是顺序执行,验证次数应该是13*4=52,但实际的验证次数会少于这个数字(我这里最近一次执行了33次验证),因为如果同时有两个线程要验证同一节点时只会做一次验证。关于时间,如果是顺序执行,52次验证每次等待500ms,那么验证所耗费的时间应该是26000ms,使用了多线程后的实际耗时远小于该数字(最近一次执行耗时4031ms)。
- package service.mock;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.CountDownLatch;
- import service.Node;
- import service.ThreadPoolService;
- import service.ValidationService;
- /**
- * 模拟执行这个环境的验证
- *
- * @author DigitalSonic
- */
- public class ValidationStarter implements Runnable {
- private List<String> entries;
- private ValidationService validationService;
- private CountDownLatch signal;
- public ValidationStarter(List<String> entries, ValidationService validationService,
- CountDownLatch signal) {
- this .entries = entries;
- this .validationService = validationService;
- this .signal = signal;
- }
- /**
- * 线程池大小为10,初始化执行一次,随后并发三个验证
- */
- public static void main(String[] args) {
- ThreadPoolService threadPoolService = new ThreadPoolService( 10 );
- ValidationService validationService = new ValidationService(threadPoolService);
- List<String> entries = new ArrayList<String>();
- CountDownLatch signal = new CountDownLatch( 3 );
- long start;
- long stop;
- for (Node node : MockNodeValidator.ENTRIES) {
- entries.add(node.getWsdl());
- }
- start = System.currentTimeMillis();
- validationService.validate(entries);
- threadPoolService.execute(new ValidationStarter(entries, validationService, signal));
- threadPoolService.execute(new ValidationStarter(entries, validationService, signal));
- threadPoolService.execute(new ValidationStarter(entries, validationService, signal));
- try {
- signal.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- stop = System.currentTimeMillis();
- threadPoolService.destoryExecutorService(1000 );
- System.out.println("实际执行验证次数: " + MockNodeValidator.getCount());
- System.out.println("实际执行时间: " + (stop - start) + "ms" );
- }
- @Override
- public void run() {
- validationService.validate(entries);
- signal.countDown();
- }
- }
=================================我是分割线==============================
本文没有覆盖java.util.concurrent中的所有内容,只是挑选一些比较常用的东西,想要获得更多详细信息请阅读JavaDoc。自打有了“轮子”理论,重复造大轮子的情况的确少了,但还是有人会做些小轮子,例如编写多线程程序时用到的小工具(线程池、锁等等),如果可以,请让自己再“懒惰”一点吧~