我正在使用 Commons Collections LRUMap(它基本上是一个经过少量修改的 LinkedHashMap)为用户的照片实现 LRU 缓存。findPhoto 方法可以在几秒钟内被调用数百次。
public class CacheHandler {
private static final int MAX_ENTRIES = 1000;
private static Map<Long, Photo> photoCache = Collections.synchronizedMap(new LRUMap(MAX_ENTRIES));
public static Map<Long, Photo> getPhotoCache() {
return photoCache;
}
}
用法:
public Photo findPhoto(Long userId){
User user = userDAO.find(userId);
if (user != null) {
Map<Long, Photo> cache = CacheHandler.getPhotoCache();
Photo photo = cache.get(userId);
if(photo == null){
if (user.isFromAD()) {
try {
photo = LDAPService.getInstance().getPhoto(user.getLogin());
} catch (LDAPSearchException e) {
throw new EJBException(e);
}
} else {
log.debug("Fetching photo from DB for external user: " + user.getLogin());
UserFile file = userDAO.findUserFile(user.getPhotoId());
if (file != null) {
photo = new Photo(file.getFilename(), "image/png", file.getFileData());
}
}
cache.put(userId, photo);
}else{
log.debug("Fetching photo from cache, user: " + user.getLogin());
}
return photo;
}else{
return null;
}
}
如您所见,我没有使用同步块。我假设这里最坏的情况是竞争条件导致两个线程为同一个 userId 运行 cache.put(userId, photo)。但是两个线程的数据是相同的,所以这不是问题。
我的推理在这里正确吗?如果没有,有没有办法使用同步块而不会对性能造成很大影响?一次只有 1 个线程访问地图感觉有点矫枉过正。