Don't naively use Java maps as a global cache in a Java Server environment.
Instead:
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>();
builder.put("123",new Person("Dave","Ford"));
builder.put("222",new Person("Joe","Blow"));
map = builder.build();
}
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()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(
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
}
}
Summary
Notice that both examples:
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>();
builder.put("123",new Person("Dave","Ford"));
builder.put("222",new Person("Joe","Blow"));
map = builder.build();
}
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()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(
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
}
}
Summary
Notice that both examples:
- Have no mutable state
- Do not use the keyword synchronized
No comments:
Post a Comment