2012-02-27 57 views
4

是否有ConcurrencyLevel超出該ConcurrentHashMap中的表現開始惡化一些最優值?的Java:ConcurrencyLevel值的ConcurrentHashMap

如果是,那是什麼價值,什麼是性能下降的原因是什麼? (這個問題從試圖找出ConcurrentHashMap可能具有的任何實際限制中找到)。

回答

4

Javadoc提供非常詳細的指導:

更新操作中允許的併發由可選concurrencyLevel構造函數的參數(默認16),它被用作內部尺寸的提示引導。

表內部劃分,試圖以允許併發更新指定數量的無爭。因爲在哈希表中放置本質上是隨機的,所以實際的併發性會有所不同。理想情況下,您應該選擇一個值來容納儘可能多的線程,就像同時修改表一樣。使用比您需要的值高得多的值可能會浪費空間和時間,而顯着更低的值可能會導致線程爭用。但是在一個數量級內高估和低估通常不會產生太多明顯的影響。當知道只有一個線程將被修改而其他所有線程只會被讀取時,值爲1是適當的。

總結:最佳值取決於預期的併發更新的數量。的是一個數量級內的值應該很好地工作。預計該範圍之外的值會導致性能下降。

+0

我看過這個文檔,但它沒有回答我的問題。假設我想要加載測試ConcurrentHashMap。那麼concurrencyLevel的值會降低它的性能,爲什麼? – shrini1000 2012-02-27 13:26:08

+1

@ shrini1000:我認爲這其實很明顯:最佳值**取決於預期的併發更新數量**。一個數量級的值應該很好。據Javadoc稱,超出該範圍的值可能會導致性能下降。 – NPE 2012-02-27 13:28:12

+0

讓我重新說明一下問題:ConcurrentHashMap可以在不降低其性能的情況下(比方說那些多線程正在同時更新)可以採用concurrencyLevel的* max *值。 – shrini1000 2012-02-27 13:32:31

4

你要問自己兩個問題

  • 我有多個CPU?
  • 有用程序是什麼比例的時間訪問相同的地圖嗎?

第一個問題告訴你可以一次訪問地圖的最大線程數。你可以有10000個線程,但是如果你只有4個cpus,最多4個會一次運行。

第二個問題告訴你,大多數這些線程將訪問地圖,並做一些有用的事情。您可以優化的地圖做一些無用的(例如微基準),但沒有一點調整這個恕我直言。假設你有一個有用的程序,它使用地圖很多。它可能會花費90%的時間做其他事情,例如IO,訪問其他地圖,構建鍵或值,使用從地圖獲取的值進行操作。假設你花費10%的時間訪問4臺CPU的機器上的地圖。這意味着您平均可以以0.4個線程訪問地圖。 (或者大約40%的時間內有一個線程)在這種情況下,併發級別1-4可以。

在任何情況下,使併發級別高於您擁有的cpus數量可能是不必要的,即使對於微基準測試也是如此。

+0

約10000個線程示例:即使最多4個線程可以同時運行*,更多的線程可以訪問它*並行*,對嗎?例如。一個線程在放置或放置 - 如果不存在操作等的過程中被預先佔用。所以我的問題更多來自這個其他用例。 – shrini1000 2012-02-27 14:02:29

+0

「一個線程在放置過程中被搶佔」,在這種情況下它未運行。它沒有鎖,並且沒有有效地訪問它。 – 2012-02-27 14:04:40

+0

不能在CPU上運行的線程不能被認爲是訪問集合。 – 2012-02-27 14:05:44

1

從Java 8開始,ConcurrentHashMapconcurrencyLevel的構造函數參數爲effectively unused,主要用於向後兼容。該實現被重新編寫爲使用每個散列箱中的第一個節點作爲該箱的鎖,而不是像早期版本中那樣使用固定數量的段/條。

簡而言之,從Java 8開始,只要您爲每個API合同設置一個肯定(非零,非負)值,不要擔心設置concurrencyLevel參數。