在多胎面阅读时重新分配地图是否安全?

时间:2016-07-22 03:52:19

标签: multithreading thread-safety

我正在分析大量的日志消息。大约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);
}

到目前为止一直很好。但是,我仍然不太确定它是否是线程安全的。任何意见都将不胜感激。

1 个答案:

答案 0 :(得分:0)

重新加载pool不是线程安全的,因为其他线程仍然可以看到pool的陈旧值。

要确保所有线程都看到最新引用,您应该使用synchronized关键字。但如果我理解正确,pool将被其他线程读取并仅在reload()内修改。如果是这种情况,您只需使用volatile

private volatile Map<String,PlatformUser> pool = 
                new ConcurrentHashMap<String, PlatformUser>();

这样可以避免任何锁争用,并提供读/写屏障。