ACTUALIZACIÓN: con Java 8, puede ser aún más simple:
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 eso es bueno!
respuesta original
Esta es una solución que se basa en the Memoizer pattern as described in JCiP. Utiliza un ConcurrentHashMap como una de las otras respuestas, pero en lugar de almacenar las instancias de Multiton directamente, lo que puede conducir a la creación de instancias no utilizadas, almacena el cálculo que conduce a la creación de Multiton. Esa capa adicional resuelve el problema de las instancias no utilizadas.
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();
}
}
Usted sabe que oí º Esta técnica se llama nunca usar el estado mutable global (excepto cuando los frameworks lo fuerzan a hacerlo). –
¿Tiene alguna evidencia de que la sincronización "costosa" (pero realmente fácil de hacer) del método 'getInstance' realmente sería significativa en su aplicación? –
No, esto es principalmente un ejercicio académico. Dado que la sincronización de Singleton ya parece ser un tema debatido, me preguntaba si la solución interna para Singletons se extiende de alguna manera a Multitons. – donnyton