[英]Which is better ConcurrentHashMap or Synchronized Hash Map in this case?
我正在寫一個實用程序類,它使用map作為緩存存儲。 現在,由於它將在多線程環境中使用。 我想出了在執行put操作時使用同步哈希圖還是使用ConcurrentHashMap(使用putIfAbsent)的用法,我仍然很困惑是否傾向於覆蓋鍵值(盡管鍵值在我的情況下是唯一的)並且兩者都存在利弊。 所以我無法決定。 我可能會建議使用其他一些緩存存儲區,但我對此更感興趣,如果這是唯一的選擇,我更想知道應該使用CHM或Hashmap 。
在程序注釋中是CHM用法,我以為我已經使用過HashMap。
public final class DateTime {
private static final Map<CountryLanguage, Locale> localeMap = new HashMap<>();
/*private static final Map<CountryLanguage, Locale> localeMap = new ConcurrentHashMap<>();*/
public static String getDateTime1(String pattern, LocalDateTime localDateTime, String language,
String country) {
if (language == null || language.isEmpty()) {
throw new NullPointerException("Language cannot be null or empty");
}
CountryLanguage countryLanguage = new CountryLanguage(language, country);
if (!localeMap.containsKey(countryLanguage)) {
synchronized (localeMap) {
// Putting double lock
if (!localeMap.containsKey(countryLanguage)) {
for (Locale locale : Locale.getAvailableLocales()) {
if (locale.getLanguage().equals(language) && locale.getCountry().equals(country)) {
localeMap.put(new CountryLanguage(language, country), locale);
}
}
}
}
}
/*for (Locale locale : Locale.getAvailableLocales()) {
if (locale.getLanguage().equals(language) && locale.getCountry().equals(country)) {
localeMap.putIfAbsent(new CountryLanguage(language, country), locale);
}
}*/
Locale locale = localeMap.get(countryLanguage);
if (locale == null) {
locale = Locale.ROOT;
}
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, locale);
return localDateTime.format(dateTimeFormatter);
}
注意:
Edit1:我沒有將整個地圖設為同步,而只是在放置操作時在地圖上使用了同步。 而且我正在使用雙重檢查以確保不存在兩個鍵值
同步HashMap:
- 每種方法都使用對象級鎖進行同步。 因此,synchMap上的get和put方法獲取一個鎖。
- 鎖定整個集合是性能開銷。 當一個線程保持該鎖時,沒有其他線程可以使用該集合。
ConcurrentHashMap :(在JDK 5中引入)
- 在對象級別沒有鎖定,鎖定的粒度要好得多。 對於
ConcurrentHashMap
,鎖可以處於哈希圖存儲桶級別。- 較低級別的鎖定的結果是您可以擁有並發的讀取器和寫入器,而這對於同步集合是不可能的。 這導致更多的可伸縮性。
- 如果一個線程試圖修改它,而另一個線程對其進行迭代,則
ConcurrentHashMap
不會引發ConcurrentModificationException
。
因此,我建議您使用ConcurrentHashMap
,它不會一直阻塞所有的“緩存”。
如果您想了解更多信息,請參見HashMap與ConcurrentHashMap
編輯:
關於此的其他一些文章: ConcurrentHashMap完全安全嗎?
我將使用ConcurrentHashMap
實現此功能:
public final class DateTime
{
private static final ConcurrentMap<CountryLanguage, Locale> localeMap = new ConcurrentHashMap<>();
public static String getDateTime1(String pattern, LocalDateTime localDateTime, String language, String country)
{
if (language == null || language.isEmpty()) {
throw new NullPointerException("Language cannot be null or empty");
}
CountryLanguage countryLanguage = new CountryLanguage(language, country);
// See if it is already there
Locale locale = localeMap.get(countryLanguage);
if (locale == null) {
// It's not there (probably), so look it up
Local candidate = null;
for (Locale l : Locale.getAvailableLocales()) {
if (l.getLanguage().equals(language) && l.getCountry().equals(country)) {
candidate = l;
break;
}
}
// If we found it, put it in the map
if (candidate != null) {
// It's possible that another thread beat us here, so use putIfAbsent()
// and check the return value
locale = localeMap.putIfAbsent(countryLanguage, candidate);
if (locale == null) {
locale = candidate;
}
}
}
if (locale == null) {
locale = Locale.ROOT;
}
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, locale);
return localDateTime.format(dateTimeFormatter);
}
}
這是線程安全的,不需要外部同步。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.