一、总论:在JDK中提供了几种并发工具类
1)CountDownLatch(同步倒数计数器:等待多线程(或者多步骤)完成)
2)CyclicBarrier(循环屏障:同步屏障)
3)Semaphore(信号量:控制并发进程数)
主要参考资料:java并发编程的艺术、Java并发——同步工具类
二、CountDownLatch(同步倒数计数器)–不仅仅用于多线程
1.作用:允许一个或多个线程等待其他线程完成操作。
CountDownLatch的构造函数接受一个int类的参数作为计数器,如果你想等待N个节点完成,那这里就传入N.
2.countDown方法:当我们调用CountDownLatch的countDown方法时,N就会减1;CountdownLatch的await方法就会阻塞当前线程,直到N变成零。
3.使用说明:由于CountDown可以用在任何地方,所以这里说的N个点,可以是N个线程,也可以说是N个步骤。
4.await方法:明确一点,countDown方法是目标线程或步骤调用的,用来通知监控线程自己的任务完成;await方法是当前线程或者主干步骤调用的,用来监控整个线程或步骤的运行状态,另外await方法一般都会伴有超时等待的await方法,这个方法在等待指定的时间后,就不会在阻塞当前线程,而是继续线程。
5.常用API
1)构造方法
CountDownLatch(int count): 构造方法参数指定了计数的次数。
2)void await():使当前线程在锁存计数器在到零之前一直阻塞等待,除非线程被中断。
3)boolean await(long timeout,TimeUnit timeUnit):使当前线程在锁存计数器在到零之前一直阻塞等待,除非线程被中断或者超出了指定等待的超时时间。
4)void countDown() 计数减1。当计数为0,则释放所有等待的线程。
5) long getCount() 返回当前计数。
6) String toString() 返回标识此锁存器及其状态的字符串
三、一个小小例子
唐僧监工三个徒弟去斩妖除魔,等到每个徒弟都打败妖怪;九九八十难才过去一难!
package multiTask.bean.countDownLatch;
import java.util.concurrent.*;
/**
* Created by zyl on 2016/12/4.
*/
public class CountDownLatchDemo {
public static void main(String[] arg) throws InterruptedException {
System.out.println("current thread ..." + Thread.currentThread().getName());
CountDownLatch count = new CountDownLatch(3);
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Worker(count, "悟空"));
executorService.execute(new Worker(count, "八戒"));
executorService.execute(new Worker(count, "沙僧"));
new Boss(count, "唐僧").awaitForWorkerDone();
System.out.println("所有事情都做完了,唐僧很满意!");
executorService.shutdown();
}
static class Boss {
private CountDownLatch count;
private String bossName;
public Boss(CountDownLatch count, String bossName) {
this.bossName = bossName;
this.count = count;
}
public void awaitForWorkerDone() throws InterruptedException {
this.count.await();
System.out.println("Boss monitor is done.");
}
}
static class Worker implements Runnable {
private CountDownLatch count;
private String workerName;
public Worker(CountDownLatch count, String workerName) {
this.count = count;
this.workerName = workerName;
}
@Override
public void run() {
System.out.println(workerName + " " + Thread.currentThread().getName() + " is running ..");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* 完成任务,锁存计数减1*
* */
this.count.countDown();
}
}
}
------
三、小结
-
CountDownLatch的实质本质与Thread的join方法一样。但join方法仅可以支持当前线程等待一个线程的结束,若需要等待多个线程,则需要逐个线程的调用join方法,非常麻烦。CountDwonLatch可以很方便的实现一个线程等待多个线程。