JUC中提供了三種常用的輔助類,通過這些輔助類可以很好的解決線程數量過多時Lock鎖的頻繁操作。這三種輔助類爲:
- CountDownLatch
- CyclicBarrier
- Semaphore
1.CountDownLatch
下圖是Jdk1.8中解釋的CountDownLatch類功能,簡單而言,在實例化時,需要傳入一個信號量,每當一個線程執行後,信號量減1,當信號量爲0時,釋放阻塞的線程。
不管你聽懂沒,看就完了!
用個小Demo模擬,需求是啓動5個線程,當5個線程執行完後,main線程才能繼續執行,如果不使用CountDownLatch,線程的調用將不可控。
public static void main(final String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 執行");
}, String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName() + "最終執行");
}
可以看出,不使用任何線程控制等方法,線程是隨計算機調度的,線程的執行順序並不是我們預期希望的。
當使用CountDownLatch,實例化時將信號量設置爲5,每當一個線程執行後,信號量減1,當5個線程執行完後,信號量爲0,main線程才執行。
public static void main(final String[] args) throws InterruptedException {
//實例化,並傳入信號初始量
CountDownLatch countDownLatch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 執行");
//信號量減1
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "最終執行");
}
2.CyclicBarrier
下圖是Jdk1.8中解釋的CyclicBarrier類功能,簡單而言,在實例化時,需要傳入一個信號量和Runnable接口,每當一個線程執行後,信號量加1,當信號量的值達到傳入的預期值,則執行方法。
不管你聽懂沒,看就完了!
這裏我們定義了只要達到3個線程,就執行方法。
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
System.out.println("---------方法執行---------");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t執行");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
3. Semaphore(信號燈)
下圖爲Jdk1.8文檔中的解釋,簡單來說,在初始化時設定一個預期值,當線程數量達到預期值,其他線程被阻塞,只有當線程使用完畢,其他線程才能重新開始搶佔資源。
不管你聽懂沒,看就完了!
public static void main(String[] args) {
Semaphore Semaphore = new Semaphore(3);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
Semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t搶佔到資源");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + "\t釋放了資源");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Semaphore.release();
}
}, String.valueOf(i)).start();
}
}
從運行結果中很容易理解,我們定義了初始值爲3,說明只要有3個線程搶佔到資源,直到他們釋放,其他資源都只能等待。