WeakHashMap by example

Usually we read following explanation about java.util.WeakHashMap
“A hashtable-based Map implementation with weak keys. An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use”
Unlike java.util.HashMap, WeakHashMap maintain weak reference for the all keys objects and strong reference of value objects. As per features of weak reference, they are more prone to be collection by GC. WeakHashMap runs some kind of unknown services to remove all the entries from collection whose keys are already garbage collected.
It means entries in weak hash map may changes over the time. Whenever there  is a need of more memory to your application, GC cycle will execute and its job is to collect all un-referenced objects or weak references. In some cases GC may collected keys of weak hash map as those are a weak references. Once keys are garbage collected , WeakHashMap’s implementation job is to clear all such entries.
 
See the following program, I have tried to create a situation where GC has to run and remove all un-referenced or weak references. Result of this WeakHashMap’s size changes time to time.
 
public class TestWeakHashMap {
    private static Map<Object, Object> global = new HashMap<Object, Object>();
    static String bigStr = "bnerobnrobnronbuiornb rtbnrnbrnbunrtbnrtnbirtnbintibnriiubnreneo;nbero;bnro;ebn" +
            ";ronbornbal;ndl;blxdnblsdnbo;ernhbel/abnesng;obnseobnl;sbnke;abnosei;bnserio;bhsrnpibnsdropbndro;" +
            "nbpserjbsp[jp[bneriopanbl;S";
    private static Map<Object, Object> map = new HashMap<Object, Object>();
    private static Map<Object, Object> weakMap = new WeakHashMap<Object, Object>();
 
    public static void main(String[] args) {
        Thread consumeMemoryThread = new Thread(new Runnable() {
            @Override
            public void run() {
                consumeMemory();
            }
        });
 
        Thread normalMapThread = new Thread(new Runnable() {
            @Override
            public void run() {
                testHashMap();
            }
        });
 
        Thread weakMapThread = new Thread(new Runnable() {
            @Override
            public void run() {
                testWeakHashMap();
            }
        });
 
        consumeMemoryThread.start();
        normalMapThread.start();
        weakMapThread.start();
 
        try {
            consumeMemoryThread.join();
            normalMapThread.join();
            weakMapThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        System.out.println("Size of HashMap = " + map.size());
        System.out.println("Size of Weak HashMap = " + weakMap.size());
 
    }
 
    /**
     * Putting values in HashMap.
     */
    public static void testWeakHashMap() {
        Object keyObj = new Object();
        weakMap.put(keyObj, new Object());
 
        for (int i = 0; i < 10000; i++) {
            weakMap.put(new Object(), bigStr);
            if (i % 1000 == 0) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
 
    }
 
    /**
     * Putting values to Weak HashMap.
     */
    public static void testHashMap() {
        Object keyObj = new Object();
        weakMap.put(keyObj, new Object());
 
        for (int i = 0; i < 10000; i++) {
            map.put(new Object(), bigStr);
            if (i % 1000 == 0) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
 
        }
 
    }
 
    /**
     * Just Consuming the memory.
     */
    public static void consumeMemory() {
        for (int i = 0; i < 1000000; i++) {
            global.put(new Object(), bigStr);
        }
 
    }
}


Output of the Program :

Size of HashMap = 10000
Size of Weak HashMap = 5001



In above program, 10000 entries have been put in both HashMap , but at end of the program , HashMap contains proper 10,000 entries but WeakHashMap contains only 5001, rest entries has been removed because of key garbage collection.

Use case : WeakHashMap is useful when an application want to store some information in memory but it is not as important as other other application specific data, for example the data which can easily be retrieved from the source in case of garbage collected .

It is an idea solution for in-memory cache implantation where cache miss is not big deal. It helps the application to maintain required information in the memory without affecting whole memory usage or avoiding OutOfMemoryException.

Disadvantage : The main limitation of the this implementation is lack of control. User can not control the garbage collection of keys by GC , there is no way to configure the keys garbage collection based some condition like least used keys, oldest keys etc.

Comments

Popular posts from this blog

Composite Design Pattern by example

State Design Pattern by Example

Eclipse command framework core expression: Property tester