问题?java 缓存机制
首先提出的是:缓存机制是什么?
所谓缓存,就是将程序或系统经常要调用的对象存在内存中,一遍其使用时可以快速调用,不必再去创建新的重复的实例。在Java中会有Java实例化对象,对象执行相应的操作,也就会意味着对数据的操作,我们把使用过的数据放入内存,当再次用的时候,就直接到内存中去拿,这样大大增加了对数据操作效率。
案例:
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import net.blogjava.frankiegao123.log.slf4j.Log;
import net.blogjava.frankiegao123.log.slf4j.LogFactory;
/**
* <p>System.Config 配置缓存</p>
*
* @author frankiegao123
* 2010-6-10 下午02:48:35
*/
@Component("configCache")
public class ConfigCache implements ConfigService {
private final static Log log = LogFactory.getLog(ConfigCache.class);
/**
* 更新缓存时记录的时间
*/
private volatile long time = 0L;
/**
* 正在更新缓存时的门闩,为 true 时表示当前没有更新缓存,为 true 时表示当前正在更新缓存
*/
private volatile boolean updateGate = true;
/**
* 缓存容器
*/
private Map<String, SysConfig> cache = new ConcurrentHashMap<String, SysConfig>();
private CommonDao commonDao;
@Autowired
public ConfigCache(CommonDao commonDao) {
this.commonDao = commonDao;
log.info("initializing cache...");
refreshCache();
time = System.currentTimeMillis();
log.info("initialized cache finished, cache size: {}, set cache time to current: {}, cache timeout: {}ms", cache.size(), time, ConfigConstant.CACHE_TIMEOUT);
}
/**
* <p>根据配置的键名获取配置值</p>
*
* @param configKey
* @return
* @author frankiegao123
* 2010-6-10 上午11:18:33
*/
public SysConfig getSysConfig(String configKey) {
long current = System.currentTimeMillis();
if(updateGate && isTimeout(current)) {
synchronized (this) {
if(updateGate) {
timeoutSynRefresh(current);
}
}
}
return cache.get(configKey);
}
/**
* <p>超时时更新缓存。该方法需要在同步环境中调用</p>
* @param current
* @author frankiegao123
* 2010-6-10 上午11:16:30
*/
private void timeoutSynRefresh(long current) {
updateGate = false;
log.info("refresh cache start..., time out: {}, size: {}, set updateGate to false", (current - time) / 1000.0, cache.size());
try {
refreshCache();
time = current;
log.info("refresh cache finished, size after update: {}, set cache time to current: {}", cache.size(), String.valueOf(time));
} catch (Exception e) {
log.error("refresh cache failed", e);
} finally {
updateGate = true;
log.info("refresh cache finished, set updateGate to true");
}
}
/**
* <p>更新缓存数据</p>
*
* @author frankiegao123
* 2010-6-10 上午11:15:55
*/
private void refreshCache() {
List<SysConfig> configs = commonDao.getSysConfigs();
for(Iterator<SysConfig> i = configs.iterator(); i.hasNext(); ) {
SysConfig config = i.next();
cache.put(config.getKey(), config);
}
commonDao.clear();
SysConfig config = cache.get(SysConfig.TEST_KEY);
if(config == null) {
log.error("refresh cache, cannot find TEST_KEY");
} else {
log.info("refresh cache, find TEST_KEY = [{}]", config.getValue());
}
}
/**
* <p>缓存是否超时</p>
*
* @param current
* @return
* @author frankiegao123
* 2010-6-10 上午11:16:12
*/
private boolean isTimeout(long current) {
return (current - time >= ConfigConstant.CACHE_TIMEOUT);
}
Collection<SysConfig> getSysConfigs() {
return Collections.unmodifiableCollection(cache.values());
}
int getSize() {
return cache.size();
}
long getTime() {
return time;
}
boolean isUpdateGate() {
return updateGate;
}
void refresh() {
time = 0L;
log.info("refresh: reset cache time to 0");
getSysConfig("none");
log.info("refresh: refresh cache finished, cache: {0}", String.valueOf(time));
}
}
/*
上面这代码的运行机制是这样的:
1:设定超时时间,当某一请求来到时缓存超过限定时间时,重新刷新缓存。没有请求来时,即便超时了也不会去主动刷新,待下一个请求来就会刷新了。
2:在刷新缓存的过程中,若有其他请求来时,这些请求继续使用旧的数据。(这一点之前考虑了很久,最后确定为这一方案,否则有一个在刷新缓存时会阻塞很多的线程。)
*/

被折叠的 条评论
为什么被折叠?



