1
\$\begingroup\$

I have implemented a LRU cache using ConcurrentLinkedHashMap. In the same map, I am purging events if my map reaches a particular limit as shown below.

I have a MAX_SIZE variable which is equivalent to 3.7 GB and as soon as my map reaches that limit, I am purging events from my map.

Below is my code:

import java.util.concurrent.ConcurrentMap;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.EvictionListener;

// does this really equal to 3.7 GB?
public static final int MAX_SIZE = 20000000; //equates to ~3.7GB with assumption that each event is 200 bytes AVG

public static EvictionListener<String, DataObject> listener = new EvictionListener<String, DataObject>() {
    public void onEviction(String key, DataObject value) {
        deleteEvents();
    }
};
public static final ConcurrentMap<String, DataObject> holder = new ConcurrentLinkedHashMap.Builder<String, DataObject>()
            .maximumWeightedCapacity(MAX_SIZE).listener(listener).build();

private static void deleteEvents() {
    int capacity = MAX_SIZE - (MAX_SIZE * (20 / 100));
    if (holder.size() >= capacity) {
        int numEventsToEvict = (MAX_SIZE * 20) / 100;
        int counter = 0;
        Iterator<String> iter = holder.keySet().iterator();
        while (iter.hasNext() && counter < numEventsToEvict) {
            String address = iter.next();
            holder.remove(address);
            System.out.println("Purging Elements: " +address);
            counter++;
        }
    }
}

// this holder map is used in below method to add the events into it.
// below method is being called from some other place.
public void addToHolderRequest(String key, DataObject stream) {
    holder.put(key, stream);
}

Below is the maven dependency I am using for this:

<dependency>
    <groupId>com.googlecode.concurrentlinkedhashmap</groupId>
    <artifactId>concurrentlinkedhashmap-lru</artifactId>
    <version>1.4</version>
</dependency>   

I am not sure whether this is the right way to do this? Does this MAX_SIZE really equates to 3.7 GB if events are of 200 bytes in average? Is there any better way to do this? I also have a background thread which call deleteEvents() method every 30 second.

\$\endgroup\$
  • 3
    \$\begingroup\$ Have you tried experimenting with Guava's Cache, or something like Caffeine? \$\endgroup\$ – h.j.k. Jan 29 '16 at 9:09
  • \$\begingroup\$ I have never heard about them. Can you provide an example how to use it in my scenario? \$\endgroup\$ – user1950349 Jan 29 '16 at 13:15
  • \$\begingroup\$ I am on Java 7 btw. \$\endgroup\$ – user1950349 Jan 29 '16 at 13:25
  • 1
    \$\begingroup\$ I second @h.j.k. Caches are Hard. Use somebody else's. \$\endgroup\$ – Eric Stein Jan 29 '16 at 14:55
  • \$\begingroup\$ Upon a closer look at your dependency usage, concurrentlinkedhashmap is closely related to the other two... the same developer is involved. Since you're on Java 7, Caffeine is out, but you can still check out Guava's Cache, which was inspired by concurrentlinkedhashmap. \$\endgroup\$ – h.j.k. Jan 29 '16 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.