ConcurrentHashMap
1、在jdk中,我們常用的map集合是 HashTable 和 HashMap 這兩個,其中HashTable是線程安全的,即裏面的每一個方法都是線程同步的方法,使用了synchronized關鍵字修飾,而HashMap是線程不安全的。
2、雖然HashTable是線程安全的,但是效率很低,所以在jdk1.5之後,在併發包中就增加了一個線程安全,效率也高的map集合,叫 ConcurrentHashMap
3、ConcurrentHashMap 是接口ConcurrentMap的實現類,它還有一個實現類,是ConcurrentskipListMap (支持併發排序功能。彌補ConcurrentHas hMa p)
4、ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個
小的HashTable,它們有自己的鎖。只要多個修改操作發生在不同的段上,它們就可以並
發進行。把一個整體分成了16個段(Segment.也就是最高支持16個線程的併發修改操作。
這也是在重線程場景時減小鎖的粒度從而降低鎖競爭的一種方案。並且代碼中大多共享變
量使用volatile關鍵字聲明,目的是第一時間獲取修改的內容,性能非常好。(這個也就是分段鎖)
CountDownLatch
CountDownLatch類位於java.util.concurrent包下,利用它可以實現類似計數器的功能。
比如有一個任務A,它要等待其他4個任務執行完畢之後才能執行,此時就可以利用CountDownLatch來實現這種功能了。
public class Test002 {
public static void main(String[] args) throws InterruptedException {
System.out.println("等待子線程執行完畢...");
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子線程," + Thread.currentThread().getName() + "開始執行...");
countDownLatch.countDown();// 每次減去1
System.out.println("子線程," + Thread.currentThread().getName() + "結束執行...");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子線程," + Thread.currentThread().getName() + "開始執行...");
//countDownLatch技術器減一
countDownLatch.countDown();
System.out.println("子線程," + Thread.currentThread().getName() + "結束執行...");
}
}).start();
// 調用當前方法主線程阻塞 直到countDown結果爲0, 阻塞變爲運行狀態
countDownLatch.await();
System.out.println("兩個子線程執行完畢....");
System.out.println("繼續主線程執行..");
}
}
分析:上面的代碼中,定義了一個全局的countDownLatch技術器,讓主線程和兩個子線程都可以訪問這個countDownLatch技術器,每一個子線程運行完,countDownLatch技術器就減一,而主線程調用了countDownLatch.await()方法,一直處於阻塞狀態,知道兩個線程都運行完,countDownLatch技術器變成0,主線程才繼續執行
注意:上面的代碼中,如果countDownLatch技術器初始值爲 1 ,而有兩個線程,此時也不會報錯,只是在一個線程執行完成後,countDownLatch變成0,主線程就會和另一個子線程競爭cpu資源