Friday, October 18, 2013

LruCache in Java

Java collections has LinkedHashMap which is a combination of a HashMap and a linked list which allows for predictable iteration order. There are two options for iteration - Based on insertion order, or based on Access order.

Now to create a Least Recently Used cache, the implementation need to use the access order for iteration and override the hook method removeEldestEntry() which should check the required size of the map to remove entries. I've posted the code in the example below.

Also present in the example is how you should *not* use the map in an multithreaded fashion. The class is not thread-safe and you end up with non deterministic behavior and the size invariant and probably other things go wrong.

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
/**
* A LRU Cache implementation based of LinkedHashMap
* This implementation is NOT thread safe
*/
public class LruCache<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private final int maxNumberOfEntries;
public LruCache(final int maxNumberOfEntries) {
super(maxNumberOfEntries + 1, 0.75f, true);
this.maxNumberOfEntries = maxNumberOfEntries;
}
@Override
public boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
return size() > maxNumberOfEntries;
}
private static final int PUT_COUNT = 1_000_000;
private static final int MAX_ENTRIES = 7;
private static final int THREAD_COUNT = 50;
/**
* Accessing the cache across multiple threads does cause indeterministic behaviour
*/
public static void main(String[] args) {
final LruCache<String, Integer> cache = new LruCache<String, Integer>(MAX_ENTRIES);
ExecutorService e = Executors.newFixedThreadPool(THREAD_COUNT);
for (int i = 0; i < PUT_COUNT; i++) {
e.submit(new Runnable() {
@Override
public void run() {
int r = ThreadLocalRandom.current().nextInt();
cache.put(Thread.currentThread().getName() + r, r);
}
});
}
e.shutdown();
System.out.println("Size of cache is " + cache.size());
}
}
view raw LruCache hosted with ❤ by GitHub

Sunday, May 19, 2013

Functional Programming Principles in Scala

I just completed the Functional Programming Principles in Scala course at https://www.coursera.org/course/progfun with my solutions at https://github.com/rrevo/progfun . It was a good experience learning both about Functional programming and Scala.
Overall the new features compared to an OO language like Java were-
  1. Higher-order functions
  2. Case classes and pattern matching
  3. Immutable collections
  4. Flexible evaluation strategies: strict/lazy/by name

It was refreshing to try and solve problems without mutation. However this also has a higher performance cost. Most of my current work is in Java and so I can translate some of these ideas to my work. Preferring immutability is a good idea for concurrency anyways and this was also brought up by Effective Java and Concurrency in Practice.

Scala as a language was also pretty interesting. Higher-order functions and the other features made code much more succinct than java. I did find myself trying to minify code into a single line at times. But at the same time this density meant that reading code at a later time was definitely much harder. Since types are also inferred, I did end up spending quite a bit of time trying to reason about the types of variables.

Java 8 will have some form of higher-order functions. That should close the gap between the languages slightly. However scala also has many other features and libraries that also have immense value. Choosing between either still depends on many other factors.

Thursday, January 03, 2013

Spring vs Guice default scopes

Spring and Guice are popular Inversion Of Control (IoC) frameworks. One of the most important aspects of IoC is how the framework creates new instances for value. This is the Scope. Some of the scopes are-

  1. Singleton (Spring default) - A single instance is created by the IoC container for the entire application lifetime.
  2. Prototype (Guice default) - A new instance is created whenever a value is needed.
In addition there are other scopes valid in a web context and custom scopes can also be defined. For additional details on scopes see Spring docs.

For stateless objects the programmer can choose either Singleton or Prototype. Guice docs recommend that prototype scope be used for Stateless objects even though only a single instance should suffice really. The rationale is to optimize for speed instead since singleton scopes require synchronization for implementation and today's JVMs are good at garbage collection.