1. 程式人生 > >concurrentHashMap和hashtable的區別,concurrentHashMap在各個版本的jdk中實現有什麼不同

concurrentHashMap和hashtable的區別,concurrentHashMap在各個版本的jdk中實現有什麼不同

這裡首先先說一下hashtable和hashMap 的區別:

    1.HashMap是非synchronized,hashTable 是synchronized;

    2.HashMap可以接受為Null的Key和value,而hashtable不能接受;(在hashtable中會提示空指標異常NullPointerException)

這裡再說一下concurrentHashMap:

jdk1.7

一下根據jdk文件翻譯

hashtable 支援檢索的一致性和更新的一致性,然而,儘管所有的操作都是執行緒安全的,更新操作都需要一致性鎖,這個操作會使得鎖住整個表時是都不可以進行操作的。相對於hashtable而言concurrentHashMap 是完全可以操作的依賴於他的執行緒安全而不是他的同步特性。檢索操作例如 get操作通常都不會阻塞,更多的重疊的操作是更新操作,例如 put和remove。檢索操作反映的是最近完成狀態

的一個結果,而更新操作更依賴於發生變化的過程。對於整體的操作例如 putAll 和clear,併發檢索的操作可能會受到插入或者刪除entries的影響。類似的,迭代器和列舉器返回的元素也會受hashtable在某個時間點的狀態的影響。這些都不會導致 ConcurrentModificationException. 不管怎麼樣,迭代器Iterators被設計成在同一時刻只能被一個執行緒訪問的。(也就是說iterator都是執行緒安全的???)

引入 concurrentLevel 也就是段segment的概念,預設值是16,這樣這些表被劃分然後被一定數量的併發更新操作時互相就不會存在競爭了,因為放置過程中在hashtables中是大體隨機的,在實際的併發過程中是不同的。比較理想的情況是,你可以選定一個值去顧及更多的併發執行緒去進行修改操作。使用一個比所需要的值高很多的值可能會浪費空間和時間,而使用一個顯然低很多的值可能導致執行緒爭用。

更加顯著高效的利用空間和時間從而減少了併發執行緒之間的競爭,相差數量級的高估和低估都會帶來顯著的影響。當僅有一個執行緒將執行修改操作,而其他所有執行緒都只是執行讀取操作時,才認為某個值是合適的。此外,重新調整此類或其他任何種類雜湊表的大小都是一個相對較慢的操作,因此,在可能的時候,提供構造方法中期望表大小的估計值是一個好主意。

concurrentHashMap實現了Map和Iterator中的所有方法,類似hashtable而不類似HashMap,不允許用Null用於設定Key或者value。

可以參考這個 https://my.oschina.net/hosee/blog/639352 帖子,詳細的介紹了其中的原理。

那麼,1.6和1.7中有什麼不同呢?

1.建立segment的過程中有些不同,和jdk6相比,在jdk7中,除了第一個segment之外,其餘的segment的建立都是採用延時建立的方式:也就是說在put操作之前都需要先判斷key對應的segment是否已經建立,如果沒有建立的話,使用ensureSegment來進行建立,這裡並沒有使用鎖的概念來建立,而是使用了Unsafe物件的getObjectVolatile()提供的原子讀語義結合CAS來確保Segment建立的原子性。(這裡unsafe)