因为系统有内存泄露问题,导致频繁的Full GC,用jmap将内存使用情况dump下来,然后通过mat分析了一下,发现是由于缓存map和更新该map的线程池导致的,截图见附件,下面这个是涉及到的类,研究了好几天这个问题,现在终于定位到具体的代码,耐于经验有限,想请教一下大家都是怎么处理系统中缓存数据的,有闲暇时间的帮看下下面的代码应该如何修改。。
还有个问题就是,定时更新run()里的程序总是不会立即执行,scheduleAtFixedRate的第二个参数设为0也不管用,只有这次执行完,下次再走这儿时cacheMap里才有上次的数据。所以只好在外面再执行一遍,总觉得这么写很奇怪
[code="java"]
public class CachedDataManager extends DataManagerDecorator {
private static ScheduledExecutorService pool;
private long timeLimited;//缓存中数据更新间隔时间 60s
private int poolSize;//线程池大小,20
private static int cacheSize;
public static Map cacheMap;// = new HashMap();
public Object getResult(final String methodName, final Map parameterMap) {
if (cacheMap == null) {
synchronized (CachedDataManager.class) {
if (cacheMap == null) {
cacheMap = new ConcurrentLinkedHashMap.Builder()
.maximumWeightedCapacity(cacheSize).build();
}
}
}
// 根据HashCode生成缓存map的key
final String mapKey = new KeyCreater(methodName, parameterMap)
.getHashCode();
// 缓存中没有该条数据则放入有定时更新策略的线程池
if (!cacheMap.containsKey(mapKey)) {
if (pool == null) {
pool = Executors.newScheduledThreadPool(poolSize);
}
pool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Object obj = dataManager.getResult(methodName, parameterMap);
cacheMap.put(mapKey, obj);
}
}, 0, timeLimited, TimeUnit.SECONDS);
} else if (cacheMap.get(mapKey) != null) {
return cacheMap.get(mapKey);
}
//因为上面的不会立即执行,所以第一次查询执行这里
Object obj = dataManager.getResult(methodName, parameterMap);
cacheMap.put(mapKey, obj);
return cacheMap.get(mapKey);
}
}
[/code]