2011-07-01 23 views
2

我知道Hashtable是同步的,所以它可以安全地用於多線程應用,而HashMap不是。Hashtable vs HashMap在單線程應用中的性能

我想知道這兩個在單個線程應用程序之間是否有任何性能差異。

(或者,何時使用其中一個?)

+0

你在說什麼特定的語言/圖書館?如果是,哪一個? – svick

+2

使用多線程訪問時,Hashtable本身並不安全 - 只有方法是同步的;它不會隱含地創建任何可能需要的更大的原子構造。考慮[Collections.synchronizedMap](http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29)以獲得類似Hashtable的語義從一個HashMap。 – 2011-07-01 20:53:10

+0

它被標記爲Java(它可能不是當你問)。 –

回答

0

是的。這是HashMap的(其中之一)默認不同步(使用synchronizedMap()使其同步;但請注意,根據您的使用情況,只需簡單的同步可能不足以保持您可能想要的所有操作的完整性做)。

+0

非常真實。任何基準(或其他原因)來爭論使用一個在另一個之上? ;-)怎麼樣一個SynchronizedMap(用Collections.synchronizedMap創建)vs Hashtable? – 2011-07-01 20:55:39

+0

我想JVM廠商的數字會有所不同,而優化好的實現可能不會是一個很大的開銷,但是,我無法想象一個沒有實際開銷的實現。據我所知,synchronizedMap()只是使得Map上的操作與Hashtable的操作相同,所以我想它是相似的。 (請注意,Hashtable和HashMap與存儲/檢索空值有關的其他區別 - API javadoc涵蓋了它,我認爲)。 –

2

以@svick提到的評論。如果您正在討論Java SDK附帶的HashtableHashMap,肯定會有性能差異,因爲HashMap不必使用​​塊,該塊具有開銷。

根據pst的要求,這裏是關於synchronized performance的一些閱讀,這裏有一點更近,regarding Java 1.4 vs Java 6在一臺機器上。

+0

但是,非*爭用環境中的開銷是什麼?有基準或鏈接到這樣的? :) – 2011-07-01 20:53:43

+0

儘管在單個線程應用程序中使用散列表,會不會有重大的性能問題? – caesarkim

+0

@pst:http://www.ibm.com/developerworks/java/library/j-threads1/index.html這就是說,我只是在暗示當然會有額外的開銷,即使這些開銷大部分都是微不足道的。 .. –

4

如果你想要一個線程安全的集合,你可以在LinkedHashMap或HashMap中使用ConcurrentHashMap或Collections.synchronizedMap()。如果你不需要一個線程安全的集合,你可以使用最後兩個。 Hashtable已被複製爲支持Map的泛型,但它也帶有許多遺留方法,它們執行相同的事情或執行相同的事情。

可以使用散列表,但是使用稍後開發的許多其他選項之一,恕我直言,將是一個更清潔的解決方案。如果你有一個需要Hashtable的庫,那麼你需要使用它,但除此之外,我會使用一個能夠滿足你需求的類,遵循最少的傳統方法進行最佳實踐。

性能差異可能爲每次通話約0.5 us。這可能或可能不重要。

但是,如果您不需要某個類型是線程安全的,則沒有充分的理由使用同步版本。如果你需要一個類型是線程安全的,你不能使用不是沒有線程安全防護的類型。

+1

但是'Hashtable'已被改進爲泛型並且符合'Map ' - 它是如何(當前)傳統? – 2011-07-01 21:25:32

+0

它並沒有被「替換」。 – EJP

+0

我需要澄清我的意思。 –

1

由於Java 7個聲稱,它可以做逃逸分析,並在某些情況下,刪除無競爭同步,我給它一個測試

public static void main(String[] args) 
{ 
    for(int i=0; i<100; i++) 
    { 
     System.out.println("-------------------"); 
     testS(); 
    } 
} 
static int N = 100_000_000; 
static void testS() 
{ 
    Object o = new Object(); 
    long t0 = System.nanoTime(); 
    for(int i=0; i<N; i++) 
     synchronized (o){} 
    long t = System.nanoTime() - t0; 
    System.out.printf("time: %,d%n", t); 
} 

我想不出逃逸分析一個簡單的例子。但是,顯然Java 7並沒有在我的測試中優化同步關閉;每個synchronized (o){}消耗一些時間。

令人驚訝的是,它僅消耗大約1個CPU週期,這太快而令人不敢相信。它應該至少包含兩個比較和設置指令;訪問L1緩存通常需要10個週期。顯然有一些硬件優化踢。

這是一個緊密的循環,而不是真正的應用程序。一般來說,討論真正的應用程序是非常困難的;即使是具體應用也很難分析。如果可能的話,我們可能應該更喜歡HashMap,據我們所知,至少在任何情況下都不會比Hashtable慢。

+0

這可能不是逃避分析,而是循環刪除...? – 2011-07-01 22:36:18

+0

它需要首先進行逃逸分析,理由是「o」對其他人不可見,所以'synchronized(o)'在它可以移除語句之前沒有任何作用。 – irreputable

0

如果您甚至可以測量真實世界測試中的差異,我會感到驚訝。如果你測量了無數的作戰行動,也許,但你不會做無數的行動,你甚至很難達到第一百萬。