我们有一个使用HashMaps和同步加载方法的简单缓存机制。这适用于WAS 8应用程序服务器。应用程序包含几个Web应用程序和后台使用JPA的Web方法。
从昨天起,它工作得很好,没有任何问题。但是有一个重要的停机时间。原因是在Web服务的一些高流量期间,发生了大量的loadData方法调用。我相信那时候地图是空的,并且即使第一次调用加载的地图,每次调用都试图执行loaddata方法。
我想到一个简单的解决方法是单独调用每个加载方法。但最终我相信我们需要一个更好的解决方案,因为这只会减少再次发生这种情况的可能性。
我知道有一些api用于缓存,并愿意深入挖掘更多。但我相信没有api就有一个好的解决方案。
那么,你对这种情况有什么建议?
编辑:只有在需要重新加载缓存时,才会手动从servlet调用loadData方法。
private static HashMap<String, Long> someObjectMap = new HashMap<String, Long>();
private static HashMap<String, Long> someAnotherObjectMap = new HashMap<String, Long>();
public synchronized static void loadData() {
loadSomeObjectMap();
loadSomeAnotherObjectMap();
// and some more methods similar, about 10 of them
}
//fill first map
public static void loadSomeObjectMap (){
someObjectMap = null;
try {
if (someObjectMap == null ) {
someObjectMap = new HashMap<String, Long>();
//fill someObjectMap here
}
} catch (Exception e) {
logger.error(Util.getStackTrace(e));
}
}
//fill second map
public static void loadSomeAnotherObjectMap (){
someAnotherObjectMap = null;
try {
if (someAnotherObjectMap == null ) {
someAnotherObjectMap = new HashMap<String, Long>();
//fill someObjectMap here
}
} catch (Exception e) {
logger.error(Util.getStackTrace(e));
}
}
答案 0 :(得分:3)
我发现你的代码很奇怪。例如:
someObjectMap = null;
try {
if (someObjectMap == null ) {
将变量设置为null
,然后立即测试,如果它是null
,有什么意义?还有那么一把锁?
public static void loadSomeObjectMap (){
为什么这种方法公开?直接调用它将绕过同步并提供数据竞争的教科书示例。
您何时致电loadData
?它是一个计划任务,以设定的间隔刷新缓存吗?这就是应该的方式,但从您的问题来看,它似乎是在每次服务呼叫时被调用的。您可能正在使用延迟初始化方案,但在您的代码中没有任何证据。
是的,你一定要用它。你现在所做的只不过是一种学习经验来说服你。在此过程中,您将遇到内存不足问题,锁定问题,GC问题,数据库问题......仅举几例。
答案 1 :(得分:0)
锁定对象而不是使用同步方法
例如
private static final Object lockObject = new Object();
private static HashMap<String, Long> someObjectMap = null;
public static void loadSomeObjectMap (){
lock(lockObject){
try {
if (someObjectMap == null ) {
someObjectMap = new HashMap<String, Long>();
//fill someObjectMap here
}
} catch (Exception e) {
logger.error(Util.getStackTrace(e));
}
}
}
或使用简单的单身人士
private static HashMap<String, Long> someObjectMap = null;
public static void loadSomeObjectMap (){
if (someObjectMap == null ) {
try {
someObjectMap = new HashMap<String, Long>();
//fill someObjectMap here
} catch (Exception e) {
someObjectMap = null ;
logger.error(Util.getStackTrace(e));
}
}
}