在 JUC 下包含了一些常用的同步工具类,今天就来详细介绍一下,CountDownLatch,CyclicBarrier,Semaphore 的使用方法以及它们之间的区别。
一、CountDownLatch
先看一下,CountDownLatch 源码的官方介绍。
意思是,它是一个同步辅助器,允许一个或多个线程一直等待,直到一组在其他线程执行的操作全部完成。
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
它的构造方法,会传入一个 count 值,用于计数。
常用的方法有两个:
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void countDown() {
sync.releaseShared(1);
}
当一个线程调用await方法时,就会阻塞当前线程。每当有线程调用一次 countDown 方法时,计数就会减 1。当 count 的值等于 0 的时候,被阻塞的线程才会继续运行。
现在设想一个场景,公司项目,线上出现了一个紧急 bug,被客户投诉,领导焦急的过来,想找人迅速的解决这个 bug 。
那么,一个人解决肯定速度慢啊,于是叫来张三和李四,一起分工解决。终于,当他们两个都做完了自己所需要做的任务之后,领导才可以答复客户,客户也就消气了(没办法啊,客户是上帝嘛)。
于是,我们可以设计一个 Worker 类来模拟单个人修复 bug 的过程,主线程就是领导,一直等待所有 Worker 任务执行结束,主线程才可以继续往下走。
public class CountDownTest {
static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
Worker w1 = new Worker("张三", 2000, latch);
Worker w2 = new Worker("李四", 3000, latch);
w1.start();
w2.start();
long startTime = System.currentTimeMillis();
latch.await();
System.out.println("bug全部解决,领导可以给客户交差了,任务总耗时: "+ (System.currentTimeMillis() - startTi