Thursday, July 19, 2012

Concurrent Maps for lightweight caching

Here is the Dave best practice when using a map for caching purposes in a java server environment:

Don't naively use Java maps as a global cache in a Java Server environment. 


If it's a create-once, read-many type cache.
Use a Guava ImmutableMap and ImmutableMapBuilder:

public class DaveMapDemo1 {

//note: Person is immutable
private final ImmutableMap<String,Person> map;

public DaveMapDemo1() {

       ImmutableMap.Builder<String,Person> builder =
new ImmutableMap.Builder<String,Person>();
"123",new Person("Dave","Ford"));
"222",new Person("Joe","Blow"));
       map =;


public Person getPerson(String id){
return map.get(id);


If it's a get-or-create type cache.
If the cache is populated lazily, use Guava's LoadingCache and CacheBuilder classes (these replace the Guava ConcurrentMap implementations):

public class DaveMapDemo2 {

//note: Person is immutable
final LoadingCache<String, Person> map;

public DaveMapDemo2() {

       map = CacheBuilder.newBuilder()
10, TimeUnit.MINUTES)
new CacheLoader<String, Person>() {
public Person load(String id) {
return lookupPersonFromDatabase(id);


public Person getPerson(String id) throws ExecutionException {
return map.get(id);

private Person lookupPersonFromDatabase(String id) {
// yada yada yada

Notice that both examples:

  1. Have no mutable state
  2. Do not use the keyword synchronized

No comments: