簡體   English   中英

在這種情況下,哪個ConcurrentHashMap或Synchronized Hash Map更好?

[英]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);
  }

注意:

  • 我有一個內部類CountryLanguage,它具有String country,String語言作為成員變量,並且hashCode和equals方法都已被覆蓋。

Edit1:我沒有將整個地圖設為同步,而只是在放置操作時在地圖上使用了同步。 而且我正在使用雙重檢查以確保不存在兩個鍵值

同步HashMap:

  1. 每種方法都使用對象級鎖進行同步。 因此,synchMap上的get和put方法獲取一個鎖。
  2. 鎖定整個集合是性能開銷。 當一個線程保持該鎖時,沒有其他線程可以使用該集合。

ConcurrentHashMap :(在JDK 5中引入)

  1. 在對象級別沒有鎖定,鎖定的粒度要好得多。 對於ConcurrentHashMap ,鎖可以處於哈希圖存儲桶級別。
  2. 較低級別的鎖定的結果是您可以擁有並發的讀取器和寫入器,而這對於同步集合是不可能的。 這導致更多的可伸縮性。
  3. 如果一個線程試圖修改它,而另一個線程對其進行迭代,則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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM