我正在分析大量的日志消息。大约10个日志分析工作线程需要从此PlatformUserPool获取用户信息,这是一个单一实例。我希望它每天在0时钟重新加载。因为重新加载成本约为5秒,我首先将记录读取到临时地图,然后将其分配给实际池。
private static final Logger LOG = Logger.getLogger(PlatformUser.class);
private Map<String,PlatformUser> pool = new ConcurrentHashMap<String, PlatformUser>();
private PlatformUserDAO platformUserDAO = new PlatformUserDAO(MorphiaFactory.getMorphia(), MongoConnection.getClient());
private static final PlatformUserPool instance = new PlatformUserPool();
private PlatformUserPool(){}
public static PlatformUserPool getInstance(){
return instance;
}
public PlatformUser getPlatformUser(String userId){
return pool.get(userId);
}
public void reload(){
try {
Iterator<PlatformUser> itr = platformUserDAO.find().iterator();
Map<String, PlatformUser> tempPool = new ConcurrentHashMap<String, PlatformUser>();
while (itr.hasNext()) {
PlatformUser user = itr.next();
if (user != null) {
tempPool.put(user.getId(), user);
}
}
pool = tempPool;
LOG.info("reload PlatformUserPool successfully.");
}catch (Exception e){
LOG.error("error occur while reloading PlatformUserPool.",e);
}
}
public void reloadDaily(){
Date now = new Date();
long time2EndOfDay = Utils.getEndOfDay(now).getTime() - now.getTime();
//reload everyday 00:00AM
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
reload();
}
},time2EndOfDay, TimeUnit.MILLISECONDS.convert(1,TimeUnit.DAYS), TimeUnit.MILLISECONDS);
}
到目前为止一直很好。但是,我仍然不太确定它是否是线程安全的。任何意见都将不胜感激。
答案 0 :(得分:0)
重新加载pool
不是线程安全的,因为其他线程仍然可以看到pool
的陈旧值。
要确保所有线程都看到最新引用,您应该使用synchronized
关键字。但如果我理解正确,pool
将被其他线程读取并仅在reload()
内修改。如果是这种情况,您只需使用volatile
:
private volatile Map<String,PlatformUser> pool =
new ConcurrentHashMap<String, PlatformUser>();
这样可以避免任何锁争用,并提供读/写屏障。