java - 加载静态缓存的最佳模式或方法是什么?

标签 java static

假设我有以下内容(假设仅限于 java 1.4,所以没有泛型):

public class CacheManager {
    static HashMap states;
    static boolean statesLoaded;

    public static String getState(String abbrev) {
        if(!statesLoaded) {
            loadStates();
        }
        return (String) states.get(abbrev);
    }

    private static void loadStates() {
        //JDBC stuff to load the data
        statesLoaded = true;
    }
}

在像 Web 应用程序服务器这样的高负载多线程环境中,如果 > 1 个线程试图同时获取和加载缓存,理论上这可能会出现问题。 (进一步假设 Web 应用程序上没有用于初始化缓存的启动代码)

仅使用 Collections.synchronizedMap 是否足以解决此问题?返回的 synchronizedMap 在执行 get() 时是否有性能问题,如果有很多线程正在访问它?

或者有一个非同步的 HashMap,而不是在加载方法或 boolean 变量上同步会更好吗?我认为,如果您同步其中任何一个,您最终可能会锁定该类。

例如,如果 load 方法是同步的,如果 2 个线程同时进入 getStates() 方法,并且都看到 statesLoaded 为 false 会怎样。第一个获取方法的锁,加载缓存并将 statesLoaded 设置为 true。不幸的是,第二个线程已经判断 statesLoaded 为 false,并在锁释放后继续执行 load 方法。它不会继续并再次加载缓存吗?

最佳答案

在这种情况下加载缓存的最佳方式是利用 JVM 静态初始化:

public class CacheManager {
    private static final HashMap states = new HashMap();

    public static String getState(String abbrev) {
        return (String) states.get(abbrev);
    }

    static {
        //JDBC stuff to load the data
    }
}

缓存将在第一次使用该类时加载,并且由于静态初始化是线程安全的,因此映射将被安全地填充。任何后续检索值的调用都可以在不涉及任何锁定的情况下完成。

尽可能利用静态初始化总是一个好主意。它安全、高效,而且通常非常简单。

关于java - 加载静态缓存的最佳模式或方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1143995/

相关文章:

java - 邮件发送失败,SMTP 连接失败

java - 检查 JLabel 的 Icon 是否为特定 Icon

git - 一种创建多语种静态网站的系统

c++ - 在 C++ 中使用多个静态库解决冲突

c++ - 在cygwin下 boost c++静态链接路径

java - 静态函数调用之前的泛型尖括号

java - 如何在android中的fragment中使用谷歌地图?

java - 有没有办法使用 java 对象作为函数的参数并在 GraalJS 中返回所述对象的值之一?

java - 使用 JButton 更新 JTable

java - 为什么最好从方法类的实例中静态调用静态方法?