What is the best template or method for loading a static cache?

Let's say I have the following (suppose there are no generics for 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;
    }
}

In a multi-threaded high-load environment, such as a web application server, a problem could theoretically occur if> 1 thread tries to retrieve and load the cache at the same time. (Assuming there is no startup code in the web application to initialize the cache)

Is using Collections.synchronizedMap just enough to fix it? Does the returned synchronizedMap have performance issues when executing get () if many threads are accessing it?

HashMap load ? , , .

, , 2 getStates(), , stateLoaded . , ​​true. , , statesLoaded , , . ?

+3
6

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
    }
}

, , . .

, . , .

+6

:

if(!statesLoaded) {
    loadStates();
}

? get() . statesLoaded, , . () , .

( , , , , , , ..)

, ( , ).

. , . , , . .

+1

. IoC, Spring , . .

0

Singleton?

public class CacheManager {

    private static class SingletonHolder
    {
        static final HashMap states;
        static
        {
            states = new HashMap();
            states.put("x", "y");
        }
    }

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

}
0

stateLoaded false true, , stateLoaded, , . , , true.

, , getState , " " .

- :

// If we safely know the states are loaded, don't even try to lock
if(!statesLoaded) {
  // I don't even pretend I know javas synchronized syntax :)
  lock(mutex); 
  // This second check makes sure we don't initialize the
  // cache multiple times since it might have changed
  // while we were waiting for the mutex
  if(!statesLoaded) {
    initializeStates();
    statesLoaded = true;
  }
  release(mutex);
}
// Now you should know that the states are loaded and they were only
// loaded once.

, .

C, , statesLoaded variable volatile, , . , Java, , , , , statesLoaded, .

0

+1 IoC. Spring. CacheManager CacheManaget Spring.

1 non-static version of CacheManager

package your.package.CacheManager;

// If you like annotation
@Component
public class CacheManager<K, V> {

    private Map<K, V> cache;

    public V get(K key) {
        if(cache != null) {
            return cache.get(key);
        }
        synchronized(cache) {
            if(cache == null) {
                loadCache();
            }
            return cache.get(key);
        }
    }

    private void loadCache() {
        cache = new HashMap<K, V>();
        // Load from JDBC or what ever you want to load
    }
}

2 Define a CacheManager bean in a Spring context or use the @ Service / @ Component annotation (do not specify a scan path for annotations)

<bean id="cacheManager" class="your.package.CacheManager"/>

3 Bring your bean cache what you want with Spring config or @Autowire annotations

<bean id="cacheClient" clas="...">
    <property name="cache" ref="cacheManager"/>
</bean>
0
source

Source: https://habr.com/ru/post/1712878/


All Articles