Java Singleton Cache Example
Problem
Given the Java cache interface below, write a singleton class that implements the interface so that no warnings are generated without using @SuppressWarnings annotations
1 2 3 4 5 6 |
//Generic Cache Interface public interface Cache<K, V> { public void put(K key, V value); public V get(K key); } |
Solution
The question is mainly about two points:
- Type checking warning must be fixed
- Singleton design pattern should be implemented
here is how I approached the problem…
- I modified the map private member to accept key and value as objects
- Singleton design pattern can be implemented by using a private constructor so that the class can not be instantiated directly. Only one instance is kept and can be returned by a special method called getInstance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//Singleton Cache public static class SingletonCache implements Cache { //Passed Object as type parameter to fix the warning issue private Map<Object, Object> map; //Constructor private static SingletonCache sc = new SingletonCache(); //Only once instance is kept during the lifecycle of the application public static SingletonCache getInstance() { return sc; } //Private constructor to prevent instantiation private SingletonCache() { map = new HashMap<Object, Object>(); } //The warning is gone by using object //variable parameters in map public void put(Object key, Object value) { map.put(key, value); } public Object get(Object key) { return map.get(key); } } |
The hash map object is shared between put and get methods so it should be protected in a multithreaded environment. Synchronization primitives such as semaphores, monitors or even simple locking can take care of that. It is a separate topic in OS design but for the sake of this exercise we will be using ConcurrentHashMap. To do that just replace HashMap with ConcurrentHashMap. You also need to import java.util.concurrent.* as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
//Thread Safe Cache public static class ThreadSafeCache implements Cache { //Shared resource that needs protection private Map<Object, Object> map; //Single instance kept private static ThreadSafeCache sc = new ThreadSafeCache(); //Access method public static ThreadSafeCache getInstance() { return sc; } //Private constructor to prevent instantiation private ThreadSafeCache() { //ConcurrentHashMap takes care of //synchronization in a a multi-threaded //environment map = new ConcurrentHashMap<Object, Object>(); } //Now this is thread safe public void put(Object key, Object value) { map.put(key, value); } //Now this is thread safe public Object get(Object key) { return map.get(key); } } |
Please use the comments section below for questions, corrections or feedback. Thanks for reading.
Line 17 in the second code sample should probably have “private”, based on the comment on the line above it.
Thanks for the correction. Now it is fixed 🙂