使用hashmap和synchronized方法调用的简单缓存机制

时间:2013-09-17 07:57:15

标签: java caching hashmap

我们有一个使用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));
    }       
}

2 个答案:

答案 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));
        }              
    }     
}