UPDATE: with Java 8, it can be even simpler:
public class Multiton {
private static final ConcurrentMap<String, Multiton> multitons = new ConcurrentHashMap<>();
private final String key;
private Multiton(String key) { this.key = key; }
public static Multiton getInstance(final String key) {
return multitons.computeIfAbsent(key, Multiton::new);
}
}
Mmm that's good!
ORIGINAL ANSWER
This is a solution which builds on the Memoizer pattern as described in JCiP. It uses a ConcurrentHashMap like one of the other answers, but instead of storing the Multiton instances directly, which can lead to creating unused instances, it stores the computation that leads to the creation of the Multiton. That additional layer solves the problem of unused instances.
public class Multiton {
private static final ConcurrentMap<Integer, Future<Multiton>> multitons = new ConcurrentHashMap<>();
private static final Callable<Multiton> creator = new Callable<Multiton>() {
public Multiton call() { return new Multiton(); }
};
private Multiton(Strnig key) {}
public static Multiton getInstance(final Integer key) throws InterruptedException, ExecutionException {
Future<Multiton> f = multitons.get(key);
if (f == null) {
FutureTask<Multiton> ft = new FutureTask<>(creator);
f = multitons.putIfAbsent(key, ft);
if (f == null) {
f = ft;
ft.run();
}
}
return f.get();
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…