我正在编写一个实用程序类,它使用map作为缓存存储。现在它将用于多线程环境。我想在执行put操作或ConcurrentHashMap(使用putIfAbsent)时使用了synchronized hashmap,如果它容易覆盖键值,我仍然感到困惑(虽然键值在我的情况下是唯一的)并且两者都有利弊。所以我无法决定。可能有一些其他缓存存储我可以用于此目的,建议但我更感兴趣知道哪个将使用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);
}
注意:
编辑1:我没有将整个地图设为同步我只是在放置操作时使用地图上的同步。我正在使用双重检查以确保不存在两个键值
答案 0 :(得分:4)
已同步的HashMap:
- 使用对象级锁定同步每个方法。所以得到 并将方法放在synchMap上获取锁。
- 锁定整个集合是一种性能开销。一个人 线程保持锁定,没有其他线程可以使用该集合。
醇>ConcurrentHashMap:(在JDK 5中引入)
- 对象级别没有锁定,锁定很多 更细的粒度。对于
ConcurrentHashMap
,锁可能位于a hashmap bucket level。- 较低级别锁定的效果是您可以拥有并发 读者和作者不可能同步 集合。这样可以提高可扩展性。
- 醇>
ConcurrentHashMap
不会抛出ConcurrentModificationException
如果一个线程试图修改它而另一个线程迭代它。
所以,我建议你ConcurrentHashMap
,它不会阻止所有&#34; cahce&#34;一直以来。
如果您想了解更多信息HashMap vs ConcurrentHashMap
修改强>
关于此事的其他一些帖子: Is ConcurrentHashMap totally safe?
答案 1 :(得分:1)
我会使用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);
}
}
这是线程安全的,不需要外部同步。