Java 线程安全映射:提高性能 公共类EntityUtils { 私有静态最终映射searchMap=newhashmap(); 私有静态映射getSearchablePathMap(字符串键) { 同步(搜索地图) { Map pathMap=searchMap.get(key); 如果(pathMap!=null)返回pathMap; pathMap=newhashmap(); 路径图。放置(…,…); ... //大规模地图人口行动 ... pathMap=集合。不可修改的映射(pathMap); searchMap.put(key,pathMap); } 返回路径图; } }
地图条目将永远不会被删除 由于人口众多,无法使用Java 线程安全映射:提高性能 公共类EntityUtils { 私有静态最终映射searchMap=newhashmap(); 私有静态映射getSearchablePathMap(字符串键) { 同步(搜索地图) { Map pathMap=searchMap.get(key); 如果(pathMap!=null)返回pathMap; pathMap=newhashmap(); 路径图。放置(…,…); ... //大规模地图人口行动 ... pathMap=集合。不可修改的映射(pathMap); searchMap.put(key,pathMap); } 返回路径图; } },java,concurrency,synchronization,Java,Concurrency,Synchronization,地图条目将永远不会被删除 由于人口众多,无法使用ConcurrentHashMap.putIfAbsent() 当key已经存在esists时,您能否建议性能改进以避免同步?get上的某些级别的同步无法避免,但可以允许并发读取。考虑使用A来保护对搜索地图的访问。只有当GET远多于PUT时,这才是合适的 public class EntityUtils { private static final Map<String, Map<String, String>> s
ConcurrentHashMap.putIfAbsent()
当
key
已经存在esists时,您能否建议性能改进以避免同步?get上的某些级别的同步无法避免,但可以允许并发读取。考虑使用A来保护对搜索地图的访问。只有当GET远多于PUT时,这才是合适的
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;
}
}
公共类EntityUtils
{
private static final ReadWriteLock RW_LOCK=new ReentrantReadWriteLock();
私有静态最终映射searchMap=newhashmap();
私有静态映射getSearchablePathMap(字符串键)
{
RW_LOCK.readLock().LOCK();
尝试
{
Map pathMap=searchMap.get(key);
如果(pathMap!=null)返回pathMap;
}
最后
{
RW_LOCK.readLock().unlock();
}
RW_LOCK.writeLock().LOCK();
尝试
{
//首先检查一下以前的写锁持有者是否为我们构建了地图
Map pathMap=searchMap.get(key);
如果(pathMap!=null)返回pathMap;
pathMap=newhashmap();
路径图。放置(…,…);
...
//大规模地图人口行动
...
pathMap=集合。不可修改的映射(pathMap);
searchMap.put(key,pathMap);
}
最后
{
RW_LOCK.writeLock().unlock();
}
返回路径图;
}
}
get上的某些级别的同步无法避免,但可以允许并发读取。考虑使用A来保护对搜索地图的访问。只有当GET远多于PUT时,这才是合适的
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;
}
}
公共类EntityUtils
{
private static final ReadWriteLock RW_LOCK=new ReentrantReadWriteLock();
私有静态最终映射searchMap=newhashmap();
私有静态映射getSearchablePathMap(字符串键)
{
RW_LOCK.readLock().LOCK();
尝试
{
Map pathMap=searchMap.get(key);
如果(pathMap!=null)返回pathMap;
}
最后
{
RW_LOCK.readLock().unlock();
}
RW_LOCK.writeLock().LOCK();
尝试
{
//首先检查一下以前的写锁持有者是否为我们构建了地图
Map pathMap=searchMap.get(key);
如果(pathMap!=null)返回pathMap;
pathMap=newhashmap();
路径图。放置(…,…);
...
//大规模地图人口行动
...
pathMap=集合。不可修改的映射(pathMap);
searchMap.put(key,pathMap);
}
最后
{
RW_LOCK.writeLock().unlock();
}
返回路径图;
}
}
在钥匙上建立锁
现在您将说可能有两个不同的字符串对象具有相同的值。为True,但可以通过请求具有相同值的所有字符串对象的唯一实例来避免此问题:
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;
}
}
这避免了对整个映射的锁定,但保证只有一个线程执行创建新映射条目的工作
当然,地图上的锁必须保留,但仅限于get和put期间。在钥匙上建立锁 现在您将说可能有两个不同的字符串对象具有相同的值。为True,但可以通过请求具有相同值的所有字符串对象的唯一实例来避免此问题:
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;
}
}
这避免了对整个映射的锁定,但保证只有一个线程执行创建新映射条目的工作
当然,映射上的锁必须保持不变,但仅在get和put期间保持不变。您可以使用多个集合来最小化影响,但允许并发写入 如果使用ConcurrentHashMap,甚至不需要锁定读取,只需锁定写入
String uniqueKey = key.intern();
公共类EntityUtils{
//2的任意幂
静态最终int并发=16;
静态最终EntityUtils[]EU=新EntityUtils[并发];
静止的{
for(int i=0;i>>16))和(并发-1);
返回EU[k].getSearchablePathMap0(键);
}
私有映射getSearchablePathMap0(字符串键){
Map pathMap=searchMap.get(key);
如果(pathMap!=null)返回pathMap;
同步(搜索地图){
pathMap=searchMap.get(key);
如果(pathMap!=null)返回pathMap;
pathMap=newhashmap();
路径图。放置(…,…);
...
//大规模地图人口行动
...
pathMap=集合。不可修改的映射(pathMap);
searchMap.put(key,pathMap);
返回路径图;
}
}
}
您可以使用多个集合来最小化影响,但允许并发写入
如果使用ConcurrentHashMap,甚至不需要锁定读取,只需锁定写入
String uniqueKey = key.intern();
公共类EntityUtils{
//2的任意幂
静态最终int并发=16;
静态最终实体utils[]EU=新实体