public class EntityUtils
{
private static final Map<String, Map<String, String>> searchMap = new HashMap<>();
private static Map<String, String> getSearchablePathMap(String key)
{
synchronized(searchMap)
{
Map<String, String> pathMap = searchMap.get(key);
if(pathMap != null) return pathMap;
pathMap = new HashMap<>();
pathMap.put(..., ...);
...
// heavy map population operations
...
pathMap = Collections.unmodifiableMap(pathMap);
searchMap.put(key, pathMap);
}
return pathMap;
}
}
永远不会删除地图条目。
由于人口众多,无法使用ConcurrentHashMap.putIfAbsent()
。
您是否可以建议性能改进以避免key
已经存在时同步?
答案 0 :(得分:3)
无法避免某些级别的get同步,但可以允许并发读取。考虑使用ReadWriteLock来保护对搜索地图的访问权限。只有在得分远远超过看跌期权时才适用。
public class EntityUtils
{
private static final ReadWriteLock RW_LOCK = new ReentrantReadWriteLock();
private static final Map<String, Map<String, String>> searchMap = new HashMap<>();
private static Map<String, String> getSearchablePathMap(String key)
{
RW_LOCK.readLock().lock();
try
{
Map<String, String> pathMap = searchMap.get(key);
if(pathMap != null) return pathMap;
}
finally
{
RW_LOCK.readLock().unlock();
}
RW_LOCK.writeLock().lock();
try
{
//first check to see if a previous holder of write lock built map for us
Map<String, String> pathMap = searchMap.get(key);
if(pathMap != null) return pathMap;
pathMap = new HashMap<>();
pathMap.put(..., ...);
...
// heavy map population operations
...
pathMap = Collections.unmodifiableMap(pathMap);
searchMap.put(key, pathMap);
}
finally
{
RW_LOCK.writeLock().unlock();
}
return pathMap;
}
}
答案 1 :(得分:1)
您可以使用多个集合来最小化影响,但允许并发写入。
如果你使用ConcurrentHashMap,你甚至不需要锁定读取,只需写入。
public class EntityUtils {
// any power of 2
static final int CONCURRENCY = 16;
static final EntityUtils[] EU = new EntityUtils[CONCURRENCY];
static {
for (int i = 0; i < CONCURRENCY; i++)
EU[i] = new EntityUtils();
}
final Map<String, Map<String, String>> searchMap
= new ConcurrentHashMap<>();
private static Map<String, String> getSearchablePathMap(String key) {
int h = key.hashCode();
int k = (h ^ (h >>> 16)) & (CONCURRENCY - 1);
return EU[k].getSearchablePathMap0(key);
}
private Map<String, String> getSearchablePathMap0(String key) {
Map<String, String> pathMap = searchMap.get(key);
if(pathMap != null) return pathMap;
synchronized(searchMap) {
pathMap = searchMap.get(key);
if(pathMap != null) return pathMap;
pathMap = new HashMap<>();
pathMap.put(..., ...);
...
// heavy map population operations
...
pathMap = Collections.unmodifiableMap(pathMap);
searchMap.put(key, pathMap);
return pathMap;
}
}
}
答案 2 :(得分:0)
在密钥上建立锁定。
现在你要说可能有两个不同的String对象具有相同的值。是的,但是可以通过请求具有相同值的所有String对象的唯一实例来避免这种情况:
String uniqueKey = key.intern();
这可以避免整个Map上的锁定,但可以保证只有一个线程可以完成创建新映射条目的工作。
当然,地图上的锁定必须保留,但仅限于获取和放置的持续时间。