### 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
- 附錄