1. 程式人生 > >面試題:HashMap HashTable ConcurrentHashMap區別

面試題:HashMap HashTable ConcurrentHashMap區別

1. Hashtable 和 HashMap


(1)區別,這兩個類主要有以下幾方面的不同:
Hashtable和HashMap都實現了Map介面,但是Hashtable的實現是基於Dictionary抽象類。

在HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。 
當get()方法返回null值時,即可以表示 HashMap中沒有該鍵,也可以表示該鍵所對應的值為null。
 因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵,而應該用containsKey()方法來判斷。
 而在Hashtable中,無論是key還是value都不能為null 。



   這兩個類最大的不同在於:
(1)Hashtable是執行緒安全的,它的方法是同步了的,可以直接用在多執行緒環境中。
(2)而HashMap則不是執行緒安全的。在多執行緒環境中,需要手動實現同步機制。




因此,在Collections類中提供了一個方法返回一個同步版本的HashMap用於多執行緒的環境:
Java程式碼
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {   
 return new SynchronizedMap<K,V>(m);   
 }  
該方法返回的是一個SynchronizedMap 的例項。

SynchronizedMap類是定義在Collections中的一個靜態內部類。
它實現了Map介面,並對其中的每一個方法實現,通過synchronized 關鍵字進行了同步控制。

2. 潛在的執行緒安全問題
上面提到Collections為HashMap提供了一個併發版本SynchronizedMap。
這個版本中的方法都進行了同步,但是這並不等於這個類就一定是執行緒安全的。
在某些時候會出現一些意想不到的結果。
如下面這段程式碼:
Java程式碼
// shm是SynchronizedMap的一個例項   
if(shm.containsKey('key')){   
        shm.remove(key);   

}  
 這段程式碼用於從map中刪除一個元素之前判斷是否存在這個元素。
 這裡的containsKey和reomve方法都是同步的,但是整段程式碼卻不是。

 考慮這麼一個使用場景:
執行緒A執行了containsKey方法返回true,準備執行remove操作;
這時另一個執行緒B開始執行,同樣執行了containsKey方法返回true,並接著執行了remove操作;
然後執行緒A接著執行remove操作時發現此時已經沒有這個元素了。
要保證這段程式碼按我們的意願工作,一個辦法就是對這段程式碼進行同步控制,但是這麼做付出的代價太大。

在進行迭代時這個問題更改明顯。Map集合共提供了三種方式來分別返回鍵、值、鍵值對的集合:
Java程式碼
Set<K> keySet();   

Collection<V> values();   

Set<Map.Entry<K,V>> entrySet();  


 在這三個方法的基礎上,我們一般通過如下方式訪問Map的元素:
Java程式碼
Iterator keys = map.keySet().iterator();   

while(keys.hasNext()){   
        map.get(keys.next());   
}  

在這裡,有一個地方需要注意的是:得到的keySet和迭代器都是Map中元素的一個“檢視”,而不是“副本” 。
問題也就出現在這裡,當一個執行緒正在迭代Map中的元素時,另一個執行緒可能正在修改其中的元素。
此時,在迭代元素時就可能會丟擲 ConcurrentModificationException異常。


為了解決這個問題通常有兩種方法,
(1)一是直接返回元素的副本,而不是檢視。這個可以通過
集合類的 toArray() 方法實現,但是建立副本的方式效率比之前有所降低,
特別是在元素很多的情況下;
(2)另一種方法就是在迭代的時候鎖住整個集合,這樣的話效率就更低了。


3. 更好的選擇:ConcurrentHashMap


java5中新增了ConcurrentMap介面和它的一個實現類ConcurrentHashMap。


ConcurrentHashMap提供了和Hashtable以及SynchronizedMap中所不同的鎖機制。
Hashtable中採用的鎖機制是一次鎖住整個hash表,從而同一時刻只能由一個執行緒對其進行操作;
而ConcurrentHashMap中則是一次鎖住一個桶。
ConcurrentHashMap預設將hash表分為16個桶,諸如get,put,remove等常用操作只鎖當前需要用到的桶。
這樣,原來只能一個執行緒進入,現在卻能同時有16個寫執行緒執行,併發效能的提升是顯而易見的。

上面說到的16個執行緒指的是寫執行緒,而讀操作大部分時候都不需要用到鎖。只有在size等操作時才需要鎖住整個hash表。

在迭代方面,ConcurrentHashMap使用了一種不同的迭代方式。
在這種迭代方式中,當iterator被建立後集合再發生改變就不再是丟擲ConcurrentModificationException,
取而代之的是  在改變時new新的資料從而不影響原有的資料 。
iterator完成後再將頭指標替換為新的資料 。
這樣iterator執行緒可以使用原來老的資料。

而寫執行緒也可以併發的完成改變。

相關推薦

試題HashMap HashTable ConcurrentHashMap區別

1. Hashtable 和 HashMap(1)區別,這兩個類主要有以下幾方面的不同:Hashtable和HashMap都實現了Map介面,但是Hashtable的實現是基於Dictionary抽象類。在HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個

HashMap,HashTable,ConcurrentHashmap區別簡述

HashTable 底層陣列+連結串列實現,無論key還是value都不能為null,執行緒安全,實現執行緒安全的方式是在修改資料時鎖住整個HashTable,效率低,ConcurrentHashMap做了相關優化 初始size為11,擴容:newsize = olesize*

hashMap,hashTable,concurrentHashmap區別 面試必備HashMapHashtableConcurrentHashMap的原理與區別

轉自  面試必備:HashMap、Hashtable、ConcurrentHashMap的原理與區別 果你去面試,面試官不問你這個問題,你來找我^_^ 下面直接來乾貨,先說這三個Map的區別: HashTable 底層陣列+連結串列實現,無論key還是value都不能為null,執行

【圖文詳細 】HDFS試題hadoop1.x和2.x架構上的區別

(1)Hadoop 1.0 Hadoop 1.0即第一代Hadoop,由分散式儲存系統HDFS和分散式計算框架MapReduce組成,其中,HDFS由一個NameNode和多個DataNode組成,MapReduce由一個JobTracker和多個TaskTracker組成,對應Hadoop

Hive試題udf,udaf,udtf的區別

Hive中有三種UDF:     1、使用者定義函式(user-defined function)UDF;     2、使用者定義聚集函式(user-defined aggregate function,UDAF); &nb

Hive試題Hive 內部表和外部表的區別

建立外部表多了external關鍵字說明以及location path. Hive中表與外部表的區別: 1、在匯入資料到外部表,資料並沒有移動到自己的資料倉庫目錄下,也就是說外部表中的資料並不是由它自己來管理的!而表則不一樣; 2、在刪除表的時候,Hive將會把屬於表的元資料和資料全

一道試題說說程序和執行緒的區別

在理解這些概念之前首選要對併發有一定的感性認識,如果伺服器同一時間內只能服務於一個客戶端,其他客戶端都再那裡傻等的話,可見其效能的低下估計會被客戶罵出翔來,因此併發程式設計應運而生,併發是網路程式設計中必須考慮的問題。實現併發的方式有多種:比如多程序、多執行緒、IO多路複用。 在理解這些概念

JAVA試題介面和抽象類的區別和聯絡

一、介面的概念: 介面(Interface),在JAVA程式語言中是一個抽象型別,是抽象方法的集合。介面通常以interface來宣告。一個類通過繼承介面的方式,從而來繼承介面的抽象方法。 如果一個類只由抽象方法和全域性常量組成,那麼這種情況下不會將其定義為一個抽象類。只

最新美團點評Java團隊試題Spark+JDK ZGC+演算法+HashMap+Redis

技術面(一、二、三面) Java 有什麼鎖型別? 有了解Spark嗎?Spark為什麼比Hadoop要快? 談談poll和epoll,epoll是同步還是非同步 JMM、老年代在什麼情況下會觸發GC、對老年代的GC會不會導致程式卡頓?(最優吞吐量和最短停頓時間)

C++試題list和vector有什麼區別

C++面試題:list和vector有什麼區別? 考點:理解list和vector的區別 出現頻率:★★★★ 解析: vector和陣列類似,它擁有一段連續的記憶體空間,並且起始地址不變,因此它能非常好的支援隨機存取(使用[]操作符訪問其中元素),但由於它的記憶體空間是連續的,所

今天做到一道試題關於堆記憶體與棧記憶體的區別

java中記憶體分配策略及堆和棧的比較   1 記憶體分配策略   按照編譯原理的觀點,程式執行時的記憶體分配有三種策略,分別是靜態的,棧式的,和堆式的.   靜態儲存分配是指在編譯時就能確定每個資料目標在執行時刻的儲存空間需求,因而在編譯時就可以給他們分配固定的記憶體空間.這種分配策略要求程式程式碼中

試題Hive on Spark與SparkSql的區別

Hive on Spark與SparkSql的區別 hive on spark大體與SparkSQL結構類似,只是SQL引擎不同,但是計算引擎都是spark! 核心程式碼 #初始化Spark SQL #匯入Spark SQL from pyspark.sql import Hiv

試題String、StringBuffer、StringBuilder的區別與聯絡

上訴三個都屬於常見物件(API):具體的使用方法此處不再詳細列舉 String類: 字串:就是由多個字元組成的一串資料,也可以看成是一個字元陣列,通過檢視API可知: (1)字串字面值(如:“abc”)可以看成是一個字串物件; (2)字串是常量,一旦被賦值就不能被改變

今天看到的一個有趣試題return *this和return this有什麼區別

      別跟我說, return *this返回當前物件, return this返回當前物件的地址(指向當前物件的指標)。       正確答案為:return *this返回的是當前物件的克隆或者本身(若返回型別為A, 則是克隆, 若返回型別為A&, 則是本

試題src與href的區別

href 是指向網路資源所在位置,建立和當前元素(錨點)或當前文件(連結)之間的連結,用於超連結。 src是指向外部資源的位置,指向的內容將會嵌入到文件中當前標籤所在位置;在請求src資源時會將其指向的資源下載並應用到文件內,例如js指令碼,img圖片和frame等元素。當瀏覽器解析到該元素時,會暫停其

試題靜態變數和例項變數的區別

在語法定義上的區別:靜態變數前要加static關鍵字,而例項變數前則不加。         在程式執行時的區別:例項變數屬於某個物件的屬性,必須建立了例項物件,其中的例項變數才會被分配空間,才能使用這個例項變數。靜態變數不屬於某個例項物件,而是屬於類,所以也稱為類變數,只要程式載入了類的位元組碼,不用建立任何

java試題spring中的BeanFactory與ApplicationContext的作用和區別

          2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,還提供了更完整的框架功能:                  a. 國際化支援                        b. 資源訪問:Resource rs = ctx. getR

試題1,程序和執行緒的區別?什麼時候用程序?什麼時候用執行緒?為什麼你的專案中用的是執行緒?為什麼不用程序?如果只有程序,對你這個專案有沒有影響?

答:首先得知道什麼是程序什麼是執行緒,我的理解是程序是指在系統中正在執行的一個應用程式;程式一旦執行就是程序,或者更專業化來說:程序是指程式執行時的一個例項,即它是程式已經執行到課中程度的資料結構的彙集。從核心的觀點看,程序的目的就是擔當分配系統資源(CPU時間、記憶體等)的

試題Integer和int的區別?在什麼時候用Integer和什麼時候用int

/*  * int是java提供的8種原始資料型別之一。Java為每個原始型別提供了封裝類,Integer是java為int提供的封裝類。int的預設值為0,  * 而Integer的預設值為null  * ,即Integer可以區分出未賦值和值為0的區別,int則無法表達

HashM-Java試題如何對HashMap按鍵值排序

Java中HashMap是一種用於儲存“鍵”和“值”資訊對的資料結構。不同於Array、ArrayList和LinkedLists,它不會維持插入元素的順序。 因此,在鍵或值的基礎上排序HashMap是一個很難的面試問題,如果你不知道如何解決的話。下面讓我們看看如何解