0

我们有一个使用 HashMaps 和同步加载方法的简单缓存机制。这是针对 WAS 8 应用程序服务器的。应用程序由几个在后台使用 JPA 的 Web 应用程序和 Web 方法组成。

从昨天开始,它运行良好,没有任何问题。但是遇到了严重的停机时间。原因是在一些 web 服务的高流量期间,发生了大量的 loadData 方法调用。我相信那时地图是空的,即使第一次调用加载地图,每次调用都试图执行 loaddata 方法。

我想到一个简单的解决方法是分别调用单独同步的每个加载方法。但最终我相信我们需要一个更好的解决方案,因为这只会减少再次发生这种情况的机会。

我知道有一些用于缓存的 api,并且愿意深入研究。但我相信有一个/一些没有 api 的好解决方案。

那么,您对这种情况有何建议?

编辑: loadData 方法仅在需要重新加载缓存时手动从 servlet 调用。

    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));
    }       
}
4

2 回答 2

3

我发现你的代码有很多奇怪之处。例如:

一:

someObjectMap = null;
try {
    if (someObjectMap == null ) {

将变量设置为null然后立即测试它有什么意义null?而所有这一切,同时持有一个锁?

二:

public static void loadSomeObjectMap (){

为什么这个方法是公开的?直接调用它会绕过同步并提供数据竞争的教科书示例。

三:

你在什么时候打电话loadData?它是一个计划任务,它以设定的时间间隔刷新缓存吗?应该是这样,但是从您的问题来看,似乎在每次服务调用时都会调用它。您可能正在使用延迟初始化方案,但在您的代码中没有证据表明这一点。

关于您对使用工业级缓存库的评论:

是的,你绝对应该使用它。你现在所做的只是让你相信这一点的学习经验。在此过程中,您将遇到内存不足问题、锁定问题、GC 问题、数据库问题……仅举几例。

于 2013-09-17T08:12:35.257 回答
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));
        }              
    }     
}
于 2013-09-17T08:03:49.937 回答