### CountDownLatch
CountDownLatch是闭锁的一种实现;CountDownLatch是在java1.5被引入;
CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行;
```
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
```
主要API:
* countDown\(\):该方法递减计数器,表示有一个事件已经发生;
* await\(\):该方法等待计时器达到零,达到零后表示需要等待的所有事件都已发生;
如果计数器的值非零,await方法会一直阻塞直到计数器为零,或者等待中的线程中断,或者等待超时;
##### 起始门\(Starting Gate\)
所有子线程等待计数器为零后一起执行
```
public class Appliction {
private final static int NUM = 10;
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(1);
for (int i = 0; i < NUM; i++) {
new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(Thread.currentThread().getName() + " started:" + System.currentTimeMillis());
}).start();
}
countDownLatch.countDown();
System.err.println("main thread exec end");
}
}
```
##### 结束门\(Ending Gate\)
等待所有子任务或子线程结束后\(计数器为零\),对执行结果进行统计或汇总
```
/**
* 假设有10块磁盘,需要10个线程同时统计磁盘空间大小,统计完成后由主线程进行汇总
*/
public class Appliction {
private final static int NUM = 10;
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(NUM);
List<Disk> tasks = new ArrayList<>(NUM);
for (int i = 0; i < NUM; i++) {
tasks.add(new Disk());
}
for (Disk dk : tasks) {
new Thread(new DiskCountTask(countDownLatch, dk)).start();
}
countDownLatch.await();
int size = tasks.stream().mapToInt(Disk::getSize).sum();
System.err.println("All disk space size:" + size);
}
}
class Disk {
private Integer size;
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}
class DiskCountTask implements Runnable {
private Disk disk;
private CountDownLatch downLatch;
public DiskCountTask(CountDownLatch downLatch, Disk disk) {
this.downLatch = downLatch;
this.disk = disk;
}
@Override
public void run() {
int size = new Random().nextInt(10);
try {
TimeUnit.SECONDS.sleep(size);
} catch (InterruptedException e) {
e.printStackTrace();
}
disk.setSize(size);
System.err.println(Thread.currentThread().getName() + " exec end[" + System.currentTimeMillis() + "], size:" + size);
downLatch.countDown();
}
}
```
设想有这样一个功能需要Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给主线程去做汇总,利用CountDownLatch来完成就非常轻松
- 简介
- 概述
- 进程vs线程
- 资源限制
- 有关并行的两个定律
- 线程同步和阻塞
- 线程阻塞
- 线程的特性
- 守护线程
- 线程异常
- Thread
- 线程状态
- 线程中断
- wait¬ify
- suspend&resume
- join&yield
- notify¬ifyAll
- Thread.sleep
- 线程任务
- Runnable
- Callable
- Future模式
- FutureTask
- 线程实现方式
- 内核线程实现
- 用户线程实现
- 混合实现
- Java线程的实现
- java与协程
- 纤程-Fiber
- 线程调度
- 多线程协作方式
- 阻塞
- 放弃
- 休眠
- 连接线程
- 线程估算公式
- 线程活跃性
- 死锁
- 线程安全性
- 对象的发布与逸出
- 构造方法溢出
- 线程封闭
- 对象的可变性
- 原子性
- 原子操作
- CPU原子操作原理
- 总线锁
- 缓存锁
- JAVA如何实现原子操作
- long和double读写操作原子性
- Adder和Accumulator
- 线程性能
- 同步工具类
- 闭锁
- CountDownLatch
- FutureTask
- 信号量
- 栅栏
- CyclicBarrier
- Exchanger
- 并发编程
- volatile
- synchronized
- 无锁
- 偏向锁
- 轻量级锁
- 锁的优缺点对比
- 锁升级
- 锁消除
- Monitor
- synchronized语法
- Mutex Lock
- synchronized实践问题
- synchronized&ReentrantLock
- Lock
- ReentrantLock
- Condition
- 读写锁
- ReadWriteLock
- StampedLock
- 线程池
- Executor
- ExecutorService
- Executors
- ThreadPoolExecutor
- RejectedExecutionHandler
- ThreadFactory
- 线程池大小公式
- 动态调整线程池大小
- Fork/Join框架
- ForkJoinPool
- CompletableFuture
- JUC并发工具包
- LockSupport
- 延时任务与周期任务
- Timer
- TimerTask
- 异构任务并行化
- CompletionService
- volatile和synchronized比较
- 锁优化
- 锁相关概念
- 悲观锁(排它锁)
- 乐观锁
- 自旋锁
- 乐观锁vs悲观锁
- JVM锁优化-锁消除
- ThreadLocal
- InheritableThreadLocal
- TransmittableThreadLocal
- ThreadLocalRandom
- 无锁
- AtomicInteger
- Unsafe
- AtomicReference
- AtomicStampedReference
- AtomicIntegerArray
- AtomicIntegerFieldUpdater
- 无锁Vector
- LongAdder
- LongAccumulator
- 常见锁类型
- 悲观锁&独占锁
- 乐观锁
- 乐观锁vs悲观锁
- 自旋锁vs适应性自旋锁
- 公平锁vs非公平锁
- 可重入锁vs非可重入锁
- 独享锁vs共享锁
- 互斥锁
- CAS
- AQS介绍
- AQS深入剖析
- AQS框架
- AQS核心思想
- AQS数据结构
- 同步状态State
- ReentrantLock vs AQS
- AQS与ReentrantLock的关联
- ReentrantLock具体实现
- 线程加入等待队列
- 等待队列中线程出队列时机
- 如何解锁
- 中断恢复后的执行流程
- ReentrantLock的可重入应用
- JUC中的应用场景
- 自定义同步工具
- CLH锁
- 并发框架
- Akka
- Disruptor-无锁缓存框架
- 常见面试题
- 两个线程交替打印A和B
- 附录