¿Cuál es una forma eficiente de implementar un patrón singleton en Java?

¿Cuál es una forma eficiente de implementar un patrón singleton en Java?

Use una enumeración:

public enum Foo { INSTANCE; } 

Joshua Bloch explicó este enfoque en su charla Effective Java Reloaded en Google I / O 2008: enlace a video . También vea las diapositivas 30-32 de su presentación ( effective_java_reloaded.pdf ):

La forma correcta de implementar un singleton serializable

 public enum Elvis { INSTANCE; private final String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } } 

Editar: una porción en línea de “Java efectiva” dice:

“Este enfoque es funcionalmente equivalente al enfoque de campo público, excepto que es más conciso, proporciona la maquinaria de serialización de forma gratuita y ofrece una garantía inamovible contra la creación de instancias múltiples, incluso frente a la serialización sofisticada o los ataques de reflexión. aún no se ha adoptado ampliamente, un tipo de enumeración de elemento único es la mejor manera de implementar un singleton “.

Dependiendo del uso, hay varias respuestas “correctas”.

Desde java5 la mejor manera de hacerlo es usar una enumeración:

 public enum Foo { INSTANCE; } 

Pre java5, el caso más simple es:

 public final class Foo { private static final Foo INSTANCE = new Foo(); private Foo() { if (INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return INSTANCE; } public Object clone() throws CloneNotSupportedException{ throw new CloneNotSupportedException("Cannot clone instance of this class"); } } 

Repasemos el código. Primero, quieres que la clase sea final. En este caso, utilicé la palabra clave final para que los usuarios sepan que es definitiva. Luego, debe hacer que el constructor sea privado para evitar que los usuarios creen su propio Foo. Lanzar una excepción desde el constructor evita que los usuarios usen la reflexión para crear un segundo Foo. A continuación, crea un campo private static final Foo para contener la única instancia y un método public static Foo getInstance() para devolverlo. La especificación de Java se asegura de que el constructor solo se invoque cuando la clase se utiliza por primera vez.

Cuando tiene un objeto muy grande o un código de construcción pesado Y también tiene otros métodos o campos estáticos accesibles que pueden usarse antes de que se necesite una instancia, entonces y solo entonces necesita usar la inicialización diferida.

Puede usar una private static class para cargar la instancia. El código se vería así:

 public final class Foo { private static class FooLoader { private static final Foo INSTANCE = new Foo(); } private Foo() { if (FooLoader.INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return FooLoader.INSTANCE; } } 

Desde la línea private static final Foo INSTANCE = new Foo(); solo se ejecuta cuando se usa realmente la clase FooLoader, esto se ocupa de la instanciación lenta y garantiza la seguridad de la ejecución de subprocesos.

Cuando también desee poder serializar su objeto, debe asegurarse de que la deserialización no cree una copia.

 public final class Foo implements Serializable { private static final long serialVersionUID = 1L; private static class FooLoader { private static final Foo INSTANCE = new Foo(); } private Foo() { if (FooLoader.INSTANCE != null) { throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return FooLoader.INSTANCE; } @SuppressWarnings("unused") private Foo readResolve() { return FooLoader.INSTANCE; } } 

El método readResolve() se asegurará de que se devuelva la única instancia, incluso cuando el objeto se serializó en una ejecución anterior de su progtwig.

Descargo de responsabilidad: acabo de resumir todas las respuestas impresionantes y las escribí en mis palabras.


Mientras implementamos Singleton tenemos 2 opciones
1. Carga lenta
2. Carga temprana

La carga lenta agrega un poco de sobrecarga (muchas cosas para ser sincero) así que úsala solo si tienes un objeto muy grande o un código de construcción pesado Y también tienes otros métodos o campos estáticos accesibles que pueden usarse antes de que se necesite una instancia, entonces y solo entonces necesita utilizar la inicialización diferida. De lo contrario, elegir una carga anticipada es una buena opción.

La forma más simple de implementar Singleton es

 public class Foo { // It will be our sole hero private static final Foo INSTANCE = new Foo(); private Foo() { if (INSTANCE != null) { // SHOUT throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { return INSTANCE; } } 

Todo está bien, excepto su singleton cargado temprano. Vamos a probar singleton cargado perezoso

 class Foo { // Our now_null_but_going_to_be sole hero private static Foo INSTANCE = null; private Foo() { if (INSTANCE != null) { // SHOUT throw new IllegalStateException("Already instantiated"); } } public static Foo getInstance() { // Creating only when required. if (INSTANCE == null) { INSTANCE = new Foo(); } return INSTANCE; } } 

Hasta ahora todo bien, pero nuestro héroe no sobrevivirá mientras lucha solo con múltiples hilos malvados que quieren muchos ejemplos de nuestro héroe. Así que vamos a protegerlo del mal multi threading

 class Foo { private static Foo INSTANCE = null; // TODO Add private shouting constructor public static Foo getInstance() { // No more tension of threads synchronized (Foo.class) { if (INSTANCE == null) { INSTANCE = new Foo(); } } return INSTANCE; } } 

pero no es suficiente para proteger a un héroe, realmente! Esto es lo mejor que podemos / debemos hacer para ayudar a nuestro héroe

 class Foo { // Pay attention to volatile private static volatile Foo INSTANCE = null; // TODO Add private shouting constructor public static Foo getInstance() { if (INSTANCE == null) { // Check 1 synchronized (Foo.class) { if (INSTANCE == null) { // Check 2 INSTANCE = new Foo(); } } } return INSTANCE; } } 

Esto se llama “Lenguaje de locking controlado doblemente”. Es fácil olvidar la statement volátil y es difícil entender por qué es necesario.
Para más detalles: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Ahora estamos seguros sobre el hilo malo, pero ¿qué pasa con la cruel serialización? Tenemos que asegurarnos de que, incluso mientras no se serializa, no se crea ningún objeto nuevo

 class Foo implements Serializable { private static final long serialVersionUID = 1L; private static volatile Foo INSTANCE = null; // Rest of the things are same as above // No more fear of serialization @SuppressWarnings("unused") private Object readResolve() { return INSTANCE; } } 

El método readResolve() se asegurará de que se devuelva la única instancia, incluso cuando el objeto se serializó en una ejecución anterior de nuestro progtwig.

Finalmente, hemos agregado suficiente protección contra los hilos y la serialización, pero nuestro código se ve voluminoso y feo. Vamos a darle una vuelta a nuestro héroe

 public final class Foo implements Serializable { private static final long serialVersionUID = 1L; // Wrapped in a inner static class so that loaded only when required private static class FooLoader { // And no more fear of threads private static final Foo INSTANCE = new Foo(); } // TODO add private shouting construcor public static Foo getInstance() { return FooLoader.INSTANCE; } // Damn you serialization @SuppressWarnings("unused") private Foo readResolve() { return FooLoader.INSTANCE; } } 

Sí, este es nuestro mismo héroe 🙂
Desde la línea private static final Foo INSTANCE = new Foo(); solo se ejecuta cuando se usa realmente la clase FooLoader , esto se ocupa de la instanciación lenta,

y está garantizado que es seguro para subprocesos.

Y hemos llegado tan lejos, aquí está la mejor manera de lograr todo lo que hicimos es la mejor manera posible

  public enum Foo { INSTANCE; } 

Que internamente será tratado como

 public class Foo { // It will be our sole hero private static final Foo INSTANCE = new Foo(); } 

Eso es todo el miedo a la serialización, los hilos y el código feo. También ENUMS singleton se inicializan lentamente .

Este enfoque es funcionalmente equivalente al enfoque de campo público, excepto que es más conciso, proporciona la maquinaria de serialización de forma gratuita y proporciona una garantía inquebrantable contra la creación de instancias múltiples, incluso frente a sofisticados ataques de serialización o reflexión. Si bien este enfoque aún no se ha adoptado ampliamente, un tipo de enumeración de elemento único es la mejor manera de implementar un singleton.

-Joshua Bloch en “Java efectivo”

Ahora es posible que se haya dado cuenta de por qué los ENUMS se consideran la mejor manera de implementar Singleton y gracias por su paciencia 🙂
Lo actualicé en mi blog .

La solución publicada por Stu Thompson es válida en Java5.0 y posterior. Pero preferiría no usarlo porque creo que es propenso a errores.

Es fácil olvidar la statement volátil y es difícil entender por qué es necesario. Sin el volátil, este código ya no sería seguro para subprocesos debido al antipatrón con locking comprobado. Consulte más sobre esto en el párrafo 16.2.4 de Java Concurrency in Practice . En resumen: este patrón (anterior a Java5.0 o sin la statement volátil) podría devolver una referencia al objeto Bar que está (aún) en un estado incorrecto.

Este patrón fue inventado para la optimización del rendimiento. Pero esto ya no es una preocupación real. El siguiente código de inicialización diferido es rápido y, lo que es más importante, más fácil de leer.

 class Bar { private static class BarHolder { public static Bar bar = new Bar(); } public static Bar getBar() { return BarHolder.bar; } } 

Thread safe en Java 5+:

 class Foo { private static volatile Bar bar = null; public static Bar getBar() { if (bar == null) { synchronized(Foo.class) { if (bar == null) bar = new Bar(); } } return bar; } } 

EDITAR : Preste atención al modificador volatile aquí. 🙂 Es importante porque sin él, el JMM (Modelo de memoria Java) no garantiza otros subprocesos para ver los cambios en su valor. La sincronización no se ocupa de eso, solo serializa el acceso a ese bloque de código.

EDIT 2 : la respuesta de @Bno detalla el enfoque recomendado por Bill Pugh (FindBugs) y es discutible mejor. Ve a leer y vota su respuesta también.

Olvídese de la inicialización lenta , es demasiado problemático. Esta es la solución más simple:

 public class A { private static final A INSTANCE = new A(); private A() {} public static A getInstance() { return INSTANCE; } } 

Asegúrate de que realmente lo necesites. Haz un google para “antipatrón único” para ver algunos argumentos en contra de eso. No hay nada intrínsecamente malo en ello, supongo, pero es solo un mecanismo para exponer algunos recursos / datos globales, así que asegúrese de que esta sea la mejor manera. En particular, he encontrado que la dependency injection es más útil, especialmente si también está usando pruebas unitarias porque DI le permite utilizar recursos burlados para fines de prueba.

No olvides que Singleton es solo un Singleton para el cargador de clases que lo cargó. Si está utilizando cargadores múltiples (Contenedores) cada uno PODRÍA tener su propia versión del Singleton.

Estoy desconcertado por algunas de las respuestas que sugieren DI como una alternativa al uso de singletons; estos son conceptos no relacionados. Puede usar DI para inyectar instancias únicas o no únicas (por ejemplo, por subproceso). Al menos esto es cierto si usa Spring 2.x, no puedo hablar de otros marcos DI.

Entonces mi respuesta al OP sería (en todo menos el código de muestra más trivial) para:

  1. Use un marco DI como Spring, luego
  2. Haga que forme parte de su configuración DI si sus dependencias son singletons, ámbito solicitado, ámbito de sesión o lo que sea.

Este enfoque le ofrece una architecture desacoplada (y por lo tanto flexible y comprobable) en la que el uso de un singleton es un detalle de implementación fácilmente reversible (siempre que cualquier singleton que use sea seguro para hilos, por supuesto).

Realmente considere por qué necesita un singleton antes de escribirlo. Hay un debate cuasirreligioso sobre su uso, con el que puede tropezar fácilmente si busca en google singletons en Java.

Personalmente trato de evitar los singletons tan a menudo como sea posible por muchas razones, una vez más la mayoría de las cuales se pueden encontrar haciendo búsquedas en Google de singletons. Siento que con frecuencia los singletons son abusados ​​porque son fáciles de entender para todos, se utilizan como un mecanismo para obtener datos “globales” en un diseño OO y se usan porque es fácil eludir la gestión del ciclo de vida de los objetos (o realmente pensando en cómo puedes hacer A desde B). Mire cosas como Inversion of Control (IoC) o Dependency Injection (DI) para un buen middleground.

Si realmente necesitas uno, wikipedia tiene un buen ejemplo de una implementación adecuada de un singleton.

Los siguientes son 3 enfoques diferentes

1) Enum

 /** * Singleton pattern example using Java Enumj */ public enum EasySingleton{ INSTANCE; } 

2) Doble locking bloqueado / carga lenta

 /** * Singleton pattern example with Double checked Locking */ public class DoubleCheckedLockingSingleton{ private static volatile DoubleCheckedLockingSingleton INSTANCE; private DoubleCheckedLockingSingleton(){} public static DoubleCheckedLockingSingleton getInstance(){ if(INSTANCE == null){ synchronized(DoubleCheckedLockingSingleton.class){ //double checking Singleton instance if(INSTANCE == null){ INSTANCE = new DoubleCheckedLockingSingleton(); } } } return INSTANCE; } } 

3) Método de fábrica estático

 /** * Singleton pattern example with static factory method */ public class Singleton{ //initailzed during class loading private static final Singleton INSTANCE = new Singleton(); //to prevent creating another instance of Singleton private Singleton(){} public static Singleton getSingleton(){ return INSTANCE; } } 

Uso Spring Framework para administrar mis singletons. No impone el “singleton-ness” de la clase (que en realidad no se puede hacer de todos modos si hay varios cargadores de clases involucrados), pero proporciona una manera muy fácil de construir y configurar diferentes fábricas para crear diferentes tipos de objetos.

Versión 1:

 public class MySingleton { private static MySingleton instance = null; private MySingleton() {} public static synchronized MySingleton getInstance() { if(instance == null) { instance = new MySingleton(); } return instance; } } 

Carga lenta, hilo seguro con locking, bajo rendimiento debido a la synchronized .

Versión 2:

 public class MySingleton { private MySingleton() {} private static class MySingletonHolder { public final static MySingleton instance = new MySingleton(); } public static MySingleton getInstance() { return MySingletonHolder.instance; } } 

Carga lenta, hilo seguro sin locking, alto rendimiento.

Wikipedia tiene algunos ejemplos de singletons, también en Java. La implementación de Java 5 se ve bastante completa y es segura para la ejecución de subprocesos (se aplica locking de doble comprobación).

Si no necesita carga lenta, simplemente intente

 public class Singleton { private final static Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return Singleton.INSTANCE; } protected Object clone() { throw new CloneNotSupportedException(); } } 

Si desea cargar de forma diferida y desea que su Singleton sea seguro para subprocesos, intente con el patrón de doble comprobación

 public class Singleton { private static Singleton instance = null; private Singleton() {} public static Singleton getInstance() { if(null == instance) { synchronized(Singleton.class) { if(null == instance) { instance = new Singleton(); } } } return instance; } protected Object clone() { throw new CloneNotSupportedException(); } } 

Como no se garantiza que funcione el patrón de doble comprobación (debido a algún problema con los comstackdores, no sé nada más al respecto), también podría intentar sincronizar todo el método getInstance o crear un registro para todos sus Singletons.

Yo diría que Enum singleton

Singleton usando enum en Java generalmente es una forma de declarar enum singleton. Enum singleton puede contener variable de instancia y método de instancia. Por razones de simplicidad, también tenga en cuenta que si está utilizando cualquier método de instancia que no sea necesario para garantizar la seguridad de la hebra de ese método, si en absoluto afecta el estado del objeto.

El uso de una enumeración es muy fácil de implementar y no tiene inconvenientes con respecto a los objetos serializables, que tienen que sortearse de las otras formas.

 /** * Singleton pattern example using Java Enum */ public enum Singleton { INSTANCE; public void execute (String arg) { //perform operation here } } 

Puede acceder a él por Singleton.INSTANCE , mucho más fácil que llamar al método getInstance() en Singleton.

1.12 Serialización de constantes de Enum

Las constantes de Enum se serializan de forma diferente a los objetos serializables o externalizables ordinarios. La forma serializada de una constante enum consiste únicamente en su nombre; los valores de campo de la constante no están presentes en la forma. Para serializar una constante enum, ObjectOutputStream escribe el valor devuelto por el método de nombre de la constante enum. Para deserializar una constante enum, ObjectInputStream lee el nombre constante de la secuencia; la constante deserializada se obtiene llamando al método java.lang.Enum.valueOf , pasando el tipo de enumeración de la constante junto con el nombre de la constante recibida como argumentos. Al igual que otros objetos serializables o externalizables, las constantes enum pueden funcionar como los objectives de las referencias posteriores que aparecen posteriormente en la secuencia de serialización.

El proceso por el que se serializan las constantes enum no se puede personalizar: cualquier writeObject específico de writeObject , readObject , readObjectNoData , writeReplace y readResolve definidos por tipos de enumeración se ignoran durante la serialización y la deserialización. De forma similar, cualquier statement de campo serialPersistentFields o serialVersionUID también se ignora: todos los tipos de enum tienen un serialVersionUID de serialVersionUID fijo de serialVersionUID . No es necesario documentar campos y datos serializables para los tipos enum, ya que no hay variación en el tipo de datos enviados.

Citado de documentos de Oracle

Otro problema con los Singleton convencionales es que una vez que implementa la interfaz Serializable , ya no permanecen Singleton porque el método readObject() siempre devuelve una nueva instancia como constructor en Java. Esto se puede evitar utilizando readResolve() y descartando la instancia recién creada reemplazando con singleton como se muestra a continuación

  // readResolve to prevent another instance of Singleton private Object readResolve(){ return INSTANCE; } 

Esto puede volverse aún más complejo si su Clase Singleton mantiene el estado, ya que necesita convertirlos en transitorios, pero con Enum Singleton, la Serialización está garantizada por JVM.


Buena lectura

  1. Patrón Singleton
  2. Enumeraciones, Singletons y Deserialización
  3. Control doblemente bloqueado y el patrón Singleton
 There are 4 ways to create a singleton in java. 1- eager initialization singleton public class Test{ private static final Test test = new Test(); private Test(){} public static Test getTest(){ return test; } } 2- lazy initialization singleton (thread safe) public class Test { private static volatile Test test; private Test(){} public static Test getTest() { if(test == null) { synchronized(Test.class) { if(test == null){test = new Test(); } } } return test; } 3- Bill Pugh Singleton with Holder Pattern (Preferably the best one) public class Test { private Test(){} private static class TestHolder{ private static final Test test = new Test(); } public static Test getInstance(){ return TestHolder.test; } } 4- enum singleton public enum MySingleton { INSTANCE; private MySingleton() { System.out.println("Here"); } } 

Es necesario verificar la expresión idiomática si necesita cargar la variable de instancia de una clase de forma perezosa. Si necesita cargar una variable estática o un singleton perezosamente, necesita la inicialización a pedido idioma del titular .

Además, si el singleton necesita ser seriada, todos los demás campos deben ser transitorios y el método readResolve () debe implementarse para mantener invariable el objeto singleton. De lo contrario, cada vez que el objeto se deserialice, se creará una nueva instancia del objeto. Lo que readResolve () hace es reemplazar el nuevo objeto leído por readObject (), que forzó a ese nuevo objeto a ser recolectado como basura ya que no hay ninguna variable que se refiera a él.

 public static final INSTANCE == .... private Object readResolve() { return INSTANCE; // original singleton instance. } 

Varias formas de hacer un objeto singleton:

  1. Según Joshua Bloch, Enum sería el mejor.

  2. también puedes usar el locking de doble comprobación.

  3. Incluso la clase estática interna se puede usar.

Enum singleton

La forma más sencilla de implementar un Singleton que es seguro para subprocesos es utilizando un Enum

 public enum SingletonEnum { INSTANCE; public void doSomething(){ System.out.println("This is a singleton"); } } 

This code works since the introduction of Enum in Java 1.5

Double checked locking

If you want to code a “classic” singleton that works in a multithreaded environment (starting from Java 1.5) you should use this one.

 public class Singleton { private static volatile Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class){ if (instance == null) { instance = new Singleton(); } } } return instance ; } } 

This is not thread-safe before 1.5 because the implementation of the volatile keyword was different.

Early loading Singleton (works even before Java 1.5)

This implementation instantiates the singleton when the class is loaded and provides thread safety.

 public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } public void doSomething(){ System.out.println("This is a singleton"); } } 

This is how to implement a simple singleton :

 public class Singleton { // It must be static and final to prevent later modification private static final Singleton INSTANCE = new Singleton(); /** The constructor must be private to prevent external instantiation */ private Singleton(){}; /** The public static method allowing to get the instance */ public static Singleton getInstance() { return INSTANCE; } } 

This is how to properly lazy create your singleton :

 public class Singleton { // The constructor must be private to prevent external instantiation private Singleton(){}; /** The public static method allowing to get the instance */ public static Singleton getInstance() { return SingletonHolder.INSTANCE; } /** * The static inner class responsible for creating your instance only on demand, * because the static fields of a class are only initialized when the class * is explicitly called and a class initialization is synchronized such that only * one thread can perform it, this rule is also applicable to inner static class * So here INSTANCE will be created only when SingletonHolder.INSTANCE * will be called */ private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } } 

Might be a little late to the game on this, but there is a lot of nuance around implementing a singleton. The holder pattern can not be used in many situations. And IMO when using a volatile – you should also use a local variable. Let’s start at the beginning and iterate on the problem. Verás a qué me refiero.


The first attempt might look something like this:

 public class MySingleton { private static MySingleton INSTANCE; public static MySingleton getInstance() { if (INSTANCE == null) { INSTANCE = new MySingleton(); } return INSTANCE; } ... } 

Here we have the MySingleton class which has a private static member called INSTANCE, and a public static method called getInstance(). The first time getInstance() is called, the INSTANCE member is null. The flow will then fall into the creation condition and create a new instance of the MySingleton class. Subsequent calls to getInstance() will find that the INSTANCE variable is already set, and therefore not create another MySingleton instance. This ensures there is only one instance of MySingleton which is shared among all callers of getInstance().

But this implementation has a problem. Multi-threaded applications will have a race condition on the creation of the single instance. If multiple threads of execution hit the getInstance() method at (or around) the same time, they will each see the INSTANCE member as null. This will result in each thread creating a new MySingleton instance and subsequently setting the INSTANCE member.


 private static MySingleton INSTANCE; public static synchronized MySingleton getInstance() { if (INSTANCE == null) { INSTANCE = new MySingleton(); } return INSTANCE; } 

Here we’ve used the synchronized keyword in the method signature to synchronize the getInstance() method. This will certainly fix our race condition. Threads will now block and enter the method one at a time. But it also creates a performance problem. Not only does this implementation synchronize the creation of the single instance, it synchronizes all calls to getInstance(), including reads. Reads do not need to be synchronized as they simply return the value of INSTANCE. Since reads will make up the bulk of our calls (remember, instantiation only happens on the first call), we will incur an unnecessary performance hit by synchronizing the entire method.


 private static MySingleton INSTANCE; public static MySingleton getInstance() { if (INSTANCE == null) { synchronize(MySingleton.class) { INSTANCE = new MySingleton(); } } return INSTANCE; } 

Here we’ve moved synchronization from the method signature, to a synchronized block that wraps the creation of the MySingleton instance. But does this solve our problem? Well, we are no longer blocking on reads, but we’ve also taken a step backward. Multiple threads will hit the getInstance() method at or around the same time and they will all see the INSTANCE member as null. They will then hit the synchronized block where one will obtain the lock and create the instance. When that thread exits the block, the other threads will contend for the lock, and one by one each thread will fall through the block and create a new instance of our class. So we are right back where we started.


 private static MySingleton INSTANCE; public static MySingleton getInstance() { if (INSTANCE == null) { synchronized(MySingleton.class) { if (INSTANCE == null) { INSTANCE = createInstance(); } } } return INSTANCE; } 

Here we issue another check from INSIDE the block. If the INSTANCE member has already been set, we’ll skip initialization. This is called double-checked locking.

This solves our problem of multiple instantiation. But once again, our solution has presented another challenge. Other threads might not “see” that the INSTANCE member has been updated. This is because of how Java optimizes memory operations. Threads copy the original values of variables from main memory into the CPU’s cache. Changes to values are then written to, and read from, that cache. This is a feature of Java designed to optimize performance. But this creates a problem for our singleton implementation. A second thread — being processed by a different CPU or core, using a different cache — will not see the changes made by the first. This will cause the second thread to see the INSTANCE member as null forcing a new instance of our singleton to be created.


 private static volatile MySingleton INSTANCE; public static MySingleton getInstance() { if (INSTANCE == null) { synchronized(MySingleton.class) { if (INSTANCE == null) { INSTANCE = createInstance(); } } } return INSTANCE; } 

We solve this by using the volatile keyword on the declaration of the INSTANCE member. This will tell the compiler to always read from, and write to, main memory, and not the CPU cache.

But this simple change comes at a cost. Because we are bypassing the CPU cache, we will take a performance hit each time we operate on the volatile INSTANCE member — which we do 4 times. We double-check existence (1 and 2), set the value (3), and then return the value (4). One could argue that this path is the fringe case as we only create the instance during the first call of the method. Perhaps a performance hit on creation is tolerable. But even our main use-case, reads, will operate on the volatile member twice. Once to check existence, and again to return its value.


 private static volatile MySingleton INSTANCE; public static MySingleton getInstance() { MySingleton result = INSTANCE; if (result == null) { synchronized(MySingleton.class) { result = INSTANCE; if (result == null) { INSTANCE = result = createInstance(); } } } return result; } 

Since the performance hit is due to operating directly on the volatile member, let’s set a local variable to the value of the volatile and operate on the local variable instead. This will decrease the number of times we operate on the volatile, thereby reclaiming some of our lost performance. Note that we have to set our local variable again when we enter the synchronized block. This ensures it is up to date with any changes that occured while we were waiting for the lock.

I wrote an article about this recently. Deconstructing The Singleton . You can find more info on these examples and an example of the “holder” pattern there. There is also a real-world example showcasing the double-checked volatile approach. Espero que esto ayude.

For JSE 5.0 and above take the Enum approach, otherwise use static singleton holder approach ( (a lazy loading approach described by Bill Pugh). Latter solution is also thread-safe without requiring special language constructs (ie volatile or synchronized).

Another argument often used against Singletons are their testability problems. Singletons are not easily mockable for testing purposes. If this turns out to be a problem, I like to make the following slight modification:

 public class SingletonImpl { private static SingletonImpl instance; public static SingletonImpl getInstance() { if (instance == null) { instance = new SingletonImpl(); } return instance; } public static void setInstance(SingletonImpl impl) { instance = impl; } public void a() { System.out.println("Default Method"); } } 

The added setInstance method allows setting a mockup implementation of the singleton class during testing:

 public class SingletonMock extends SingletonImpl { @Override public void a() { System.out.println("Mock Method"); } } 

This also works with early initialization approaches:

 public class SingletonImpl { private static final SingletonImpl instance = new SingletonImpl(); private static SingletonImpl alt; public static void setInstance(SingletonImpl inst) { alt = inst; } public static SingletonImpl getInstance() { if (alt != null) { return alt; } return instance; } public void a() { System.out.println("Default Method"); } } public class SingletonMock extends SingletonImpl { @Override public void a() { System.out.println("Mock Method"); } } 

This has the drawback of exposing this functionality to the normal application too. Other developers working on that code could be tempted to use the ´setInstance´ method to alter alter a specific function and thus changing the whole application behaviour, therefore this method should contain at least a good warning in it’s javadoc.

Still, for the possibility of mockup-testing (when needed), this code exposure may be an acceptable price to pay.

simplest singleton class

 public class Singleton { private static Singleton singleInstance = new Singleton(); private Singleton() {} public static Singleton getSingleInstance() { return singleInstance; } } 

I still think after java 1.5, enum is the best available singleton implementation available as it also ensures that even in the multi threaded environments – only one instance is created.

public enum Singleton{ INSTANCE; }

and you are done !!!

Have a look at this post.

Ejemplos de patrones de diseño GoF en las bibliotecas centrales de Java

From the best answer’s “Singleton” section,

Singleton (recognizeable by creational methods returning the same instance (usually of itself) everytime)

  • java.lang.Runtime#getRuntime()
  • java.awt.Desktop#getDesktop()
  • java.lang.System#getSecurityManager()

You can also learn the example of Singleton from Java native classes themselves.

  1. In single-thread Selenium tests for web sites I implement WebDriver as a singleton.

  2. Sometimes it’s worth to make logger a singleton. It’s efficient when you need to collect messages from a whole application and at the end dump them to a file.

Sometimes a simple ” static Foo foo = new Foo(); ” is not enough. Just think of some basic data insertion you want to do.

On the other hand you would have to synchronize any method that instantiates the singleton variable as such. Synchronisation is not bad as such, but it can lead to performance issues or locking (in very very rare situations using this example. The solution is

 public class Singleton { private static Singleton instance = null; static { instance = new Singleton(); // do some of your instantiation stuff here } private Singleton() { if(instance!=null) { throw new ErrorYouWant("Singleton double-instantiation, should never happen!"); } } public static getSingleton() { return instance; } } 

Now what happens? The class is loaded via the class loader. Directly after the class was interpreted from a byte Array, the VM executes the static { } – block. that’s the whole secret: The static-block is only called once, the time the given class (name) of the given package is loaded by this one class loader.

 public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton(){ if (INSTANCE != null) throw new IllegalStateException (“Already instantiated...”); } public synchronized static Singleton getInstance() { return INSTANCE; } } 

As we have added the Synchronized keyword before getInstance, we have avoided the race condition in the case when two threads call the getInstance at the same time.