Java多线程与并发库高级应用之倒计时计数器

CountDownLatch
类是一个倒计时计数器,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数初始化
CountDownLatch。由于调用了countDown() 方法,所以在当前计数到达零之前,await
方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。

CountDownLatch
是一个通用同步工具,它有很多用途。将计数1初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown()
的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用N初始化的 CountDownLatch
可以使一个线程在N个线程完成某项操作之前一直等待,或者使其在某项操作完成N次之前一直等待。

CountDownLatch犹如比赛的发令官,多条线程犹如运动员。倒计时到零时一声枪响,运动员开始比赛,即多条线程开始运行。

使用CountDownLatch很简单,因为它只提供了一个构造器:

CountDownLatch(int
count):构造一个用给定计数初始化的CountDownLatch。

在线程中调用CountDownLatch对象的await()方法,会使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。而调用countDown()方法会递减锁存器的计数,如果计数到达零,则释放所有等待的线程。

见下面程序:启动三个线程等待主线程发布命令,主线程发布命令后等待三个线程运行完后的反馈。

[java] view plaincopy

  1. public class CountDownLatchDemo {
  2. public static void main(String[] args) {
  3. //线程池

  4. ExecutorService pool = Executors.newCachedThreadPool();

  5. //定义两个倒计时计数器

  6. //等待命令倒计时计数器

  7. final CountDownLatch countOrder = new CountDownLatch(1);

  8. //等待反馈倒计时计数器

  9. final CountDownLatch countAnswer = new CountDownLatch(3);
  10. //3个子线程

  11. for(int i = 0; i < 3; i++){

  12. Runnable target = new Runnable() {

  13. @Override

  14. public void run() {

  15. try {

  16. System.out.println(Thread.currentThread().getName() +

  17. "-等待命令");

  18. //等待countOrder为0时停止等待,向下执行

  19. countOrder.await();
  20. System.out.println(Thread.currentThread().getName() +

  21. "-得到命令,开始执行");

  22. Thread.sleep((long)(Math.random()*10000));

  23. System.out.println(Thread.currentThread().getName() +

  24. "-命令执行完成,回应结果");

  25. //将countAnswer减一

  26. countAnswer.countDown();

  27. } catch (InterruptedException e) {

  28. e.printStackTrace();

  29. }
  30. }

  31. };

  32. pool.execute(target);

  33. }
  34. //主线程

  35. try{

  36. Thread.sleep((long)(Math.random()*10000));

  37. System.out.println(Thread.currentThread().getName() +

  38. "-即将发布命令");

  39. //将countOrder减一

  40. countOrder.countDown();

  41. System.out.println(Thread.currentThread().getName() +

  42. "-已发布命令,等待回应");

  43. //等待回应

  44. countAnswer.await();

  45. System.out.println(Thread.currentThread().getName() +

  46. "-已收到所有回应结果");

  47. }catch(InterruptedException e) {

  48. e.printStackTrace();

  49. }
  50. pool.shutdown();

  51. }
  52. }


运行程序

看到3个子线程在接到主线程命令前都等待,当主线程调用了countDown()
方法后减为零,3个子线程开始运行,并且主线程等待子线程运行完后的回应。3个子线程没运行完一个调用countDown()
方法,当3个都运行完后,主线程收到回应。

Java多线程与并发库高级应用之倒计时计数器,码迷,mamicode.com

时间: 04-30

Java多线程与并发库高级应用之倒计时计数器的相关文章

Java多线程与并发库高级应用之公共屏障点CyclicBarrier

一个小队去登山,每位队员登山的速度不同.山上有几个集合点,在每一集合点处,先到达的队员只有等后面的队员全部到达集合点后才能继续向下一个集合点出发. JDK1.5提供的CyclicBarrier模拟了这种情况.每一个线程相当于一个登山队员,CyclicBarrier相当于山上的集合点.只有等所有线程都执行到了CyclicBarrier后才可以继续向下执行. CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程

Java多线程与并发库高级应用之信号量Semaphore

JDK1.5提供了一个计数信号量Semaphore类.Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目,并提供了同步机制. Semaphore提供了两个构造器来创建对象: 1)Semaphore(int permits):创建具有给定的许可数和非公平的公平设置的Semaphore. 2)Semaphore(int permits, boolean fair):创建具有给定的许可数和给定的公平设置的Semaphore.如果此信号量保证在争用时按先进先出的顺序授予许可,则为

Java多线程与并发库高级应用之阻塞队列BlockingQueue

JDK1.5提供了阻塞队列接口BlockingQueue,它是一个有界阻塞队列.BlockingQueue实现是线程安全的,可以安全地与多个生产者和多个使用者一起使用. 使用时用其实现类 ArrayBlockingQueue,它一个由数组支持的有界阻塞队列.此队列按 FIFO(先进先出)原则对元素进行排序.队列的头部 是在队列中存在时间最长的元素.队列的尾部是在队列中存在时间最短的元素.新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素. 这是一个典型的"有界缓存区",固定

Java多线程与并发库高级应用之线程数据交换Exchanger

JDK1.5提供了Exchanger用于两个线程的数据交换.两个线程先后到达交换点,先到达的线程会等待后到达的线程,然后两个线程互相交换数据,交换后双方持对方的数据. Exchanger只提供了一个构造器: Exchanger():创建一个新的Exchanger. Exchanger中也只有两个方法: V exchange(V x): 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象. V exchange(V x, long timeout,

Java多线程与并发库高级应用-java5线程并发库

java5 中的线程并发库 主要在java.util.concurrent包中 还有 java.util.concurrent.atomic子包和java.util.concurrent.lock子包

Java多线程与并发库高级应用 学习笔记 1-9课

来源XXX,免得打广告嫌疑. http://www.cnblogs.com/whgw/archive/2011/10/03/2198506.html 今天看了文章才发现创建线程最佳方式为实现Runnable接口,之前的习惯要改鲁. http://blog.csdn.net/imzoer/article/details/8500670 Java中Timer的用法 package timer; import java.util.Calendar; import java.util.Timer; im

Java多线程与并发库高级应用

1.传统线程机制的回顾 1.1创建线程的两种传统方式 在Thread子类覆盖的run方法中编写运行代码 // 1.使用子类,把代码放到子类的run()中运行 Thread thread = new Thread() { @Override public void run() { while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.p

Java多线程与并发库高级应用-传统定时器技术回顾

传统定时器技术回顾(jdk1.5以前) public class TraditionalTimerTest { static int count = 0; public static void main(String[] args) { //10秒后开始执行,每隔3秒执行一次 new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("bombing..."); } }

【Java多线程与并发库】4.传统线程同步通信技术

我们先通过一道面试题来了解传统的线程同步通信. 题目:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次,请写出程序. 我没有看答案,先用自己的思路写了一段代码,有一些是借鉴传统的“生产者与消费者”的多线程模型写出来的:[java] view plain copy 在CODE上查看代码片派生到我的代码片package cn.edu.hpu.test; /** * 要求的操作: * 子线程循环10次,接着主线程循环100次,接着又回