Qual è un modo efficace per implementare un modello singleton in Java?

Qual è un modo efficace per implementare un modello singleton in Java?

Usa un enum:

public enum Foo { INSTANCE; } 

Joshua Bloch ha spiegato questo approccio nel suo talk Effective Java Reloaded su Google I / O 2008: link al video . Vedi anche le diapositive 30-32 della sua presentazione ( effective_java_reloaded.pdf ):

Il modo giusto per implementare un Singleton serializzabile

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

Modifica: una porzione online di “Effective Java” dice:

“Questo approccio è funzionalmente equivalente all’approccio del campo pubblico, tranne che è più conciso, fornisce il meccanismo di serializzazione gratuito e fornisce una garanzia ferrea contro l’istanziazione multipla, anche di fronte a sofisticati attacchi di serializzazione o riflessione. ma per essere ampiamente adottato, un tipo di enum a elemento singolo è il modo migliore per implementare un singleton . ”

A seconda dell’utilizzo, ci sono diverse risposte “corrette”.

Dal momento che java5 il modo migliore per farlo è usare un enum:

 public enum Foo { INSTANCE; } 

Pre java5, il caso più semplice è:

 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"); } } 

Andiamo oltre il codice. Primo, vuoi che la lezione sia definitiva. In questo caso, ho usato la parola chiave final per far sapere agli utenti che è definitiva. Quindi è necessario rendere privato il costruttore per impedire agli utenti di creare il proprio Foo. Lanciare un’eccezione dal costruttore impedisce agli utenti di usare il riflesso per creare un secondo Foo. Quindi si crea un campo private static final Foo per mantenere l’unica istanza e un metodo public static Foo getInstance() per restituirlo. Le specifiche Java assicurano che il costruttore venga chiamato solo quando la class viene utilizzata per la prima volta.

Quando si dispone di un object molto big o di un codice di costruzione pesante, nonché di altri metodi o campi statici accessibili che potrebbero essere utilizzati prima che sia necessaria un’istanza, solo allora è necessario utilizzare l’inizializzazione pigra.

È ansible utilizzare una private static class per caricare l’istanza. Il codice sarebbe quindi simile a:

 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; } } 

Dal momento che la riga private static final Foo INSTANCE = new Foo(); viene eseguito solo quando viene effettivamente utilizzata la class FooLoader, questo si occupa dell’istanza lazy ed è garantito che sia thread-safe.

Quando vuoi anche essere in grado di serializzare il tuo object, devi assicurarti che la deserializzazione non crei 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; } } 

Il metodo readResolve() si readResolve() che venga restituita l’unica istanza, anche quando l’object è stato serializzato in una precedente esecuzione del programma.

Disclaimer: ho appena riassunto tutte le risposte fantastiche e l’ho scritto nelle mie parole.


Durante l’implementazione di Singleton abbiamo 2 opzioni
1. Caricamento lento
2. Caricamento iniziale

Il caricamento lento aggiunge bit overhead (molto onesto), quindi usalo solo quando hai un object molto big o un codice di costruzione pesante e hai anche altri metodi statici accessibili o campi che potrebbero essere utilizzati prima che sia necessaria un’istanza, quindi e solo allora è necessario utilizzare l’inizializzazione pigra. In caso contrario, scegliere il caricamento anticipato è una buona scelta.

Il modo più semplice per implementare Singleton è

 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; } } 

Tutto è buono tranne il suo singleton caricato in anticipo. Proviamo il singleton caricato pigro

 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; } } 

Fin qui tutto bene, ma il nostro eroe non sopravviverà combattendo da solo con molteplici fili del male che vogliono molti esempi del nostro eroe. Quindi, proteggilo dal multi threading malvagio

 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; } } 

ma non è abbastanza per proteggere l’eroe, Davvero !!! Questo è il meglio che possiamo / dovremmo fare per aiutare il nostro eroe

 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; } } 

Questo è chiamato “idioma di blocco a doppio controllo”. È facile dimenticare la dichiarazione volatile e difficile capire perché sia ​​necessario.
Per dettagli: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Ora siamo sicuri del filo del male, ma per quanto riguarda la serializzazione crudele? Dobbiamo assicurarci che anche durante la de-serializzazione non venga creato alcun nuovo object

 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; } } 

Il metodo readResolve() si assicurerà che l’unica istanza venga restituita, anche quando l’object è stato serializzato in una precedente esecuzione del nostro programma.

Finalmente abbiamo aggiunto una protezione sufficiente contro i thread e la serializzazione, ma il nostro codice sembra voluminoso e brutto. Lasciamo che il nostro eroe faccia una fine

 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ì, questo è il nostro stesso eroe 🙂
Dal momento che la riga private static final Foo INSTANCE = new Foo(); viene eseguito solo quando viene effettivamente utilizzata la class FooLoader , questo si occupa dell’istanza lazy,

ed è garantito per essere thread-safe.

E siamo arrivati ​​così lontano, ecco il modo migliore per ottenere tutto ciò che abbiamo fatto è il modo migliore ansible

  public enum Foo { INSTANCE; } 

Che internamente sarà trattato come

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

Non c’è più paura della serializzazione, dei thread e del brutto codice. Anche ENUMS singleton viene inizializzato pigramente .

Questo approccio è funzionalmente equivalente all’approccio del campo pubblico, tranne che è più conciso, fornisce il meccanismo di serializzazione gratuito e fornisce una garanzia ferrea contro l’istanziazione multipla, anche di fronte a sofisticati attacchi di serializzazione o riflessione. Sebbene questo approccio debba ancora essere ampiamente adottato, un tipo di enum a elemento singolo è il modo migliore per implementare un singleton.

-Joshua Bloch in “Effective Java”

Ora potresti aver capito perché ENUMS è considerato il modo migliore per implementare Singleton e grazie per la tua pazienza 🙂
Aggiornato sul mio blog .

La soluzione pubblicata da Stu Thompson è valida in Java5.0 e versioni successive. Ma preferirei non usarlo perché penso che sia sobject a errori.

È facile dimenticare la dichiarazione volatile e difficile capire perché sia ​​necessario. Senza la volatilità, questo codice non sarebbe più sicuro per il thread grazie all’antenna antifurto a doppio controllo. Per ulteriori informazioni, consultare il paragrafo 16.2.4 di Concurrency in Practice . In breve: questo pattern (precedente a Java5.0 o senza l’istruzione volatile) potrebbe restituire un riferimento all’object Bar che è (ancora) in uno stato errato.

Questo modello è stato inventato per l’ottimizzazione delle prestazioni. Ma questa non è davvero una vera preoccupazione. Il seguente codice di inizializzazione pigro è veloce e, soprattutto, più facile da leggere.

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

Thread sicuro in 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; } } 

EDIT : Prestare attenzione al modificatore volatile qui. 🙂 È importante perché senza di esso, altri thread non sono garantiti dal JMM (Java Memory Model) per vedere le modifiche al suo valore. La sincronizzazione non si occupa di questo: serializza solo l’accesso a quel blocco di codice.

EDIT 2 : la risposta di @Bno descrive l’approccio raccomandato da Bill Pugh (FindBugs) ed è discutibile meglio. Leggi e vota anche la sua risposta.

Dimentica l’ inizializzazione pigra , è troppo problematico. Questa è la soluzione più semplice:

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

Assicurati di averne davvero bisogno. Fai un google per “singleton anti-pattern” per vedere alcuni argomenti contro di esso. Non c’è nulla di intrinsecamente sbagliato in esso, suppongo, ma è solo un meccanismo per esporre alcuni dati / risorse globali, quindi assicurati che questo sia il modo migliore. In particolare, ho trovato che l’iniezione di dipendenza è più utile in particolare se si utilizzano anche i test unitari perché DI consente di utilizzare risorse fittizie a scopo di test.

Non dimenticare che Singleton è solo un Singleton per il Classloader che lo ha caricato. Se si utilizzano più caricatori (contenitori), ogni COULD dispone della propria versione di Singleton.

Sono confuso da alcune delle risposte che suggeriscono DI come alternativa all’uso dei singleton; questi sono concetti non correlati. È ansible utilizzare DI per iniettare istanze singleton o non-singleton (es. Per-thread). Almeno questo è vero se usi Spring 2.x, non posso parlare per altri framework DI.

Quindi la mia risposta all’OP sarebbe (in tutto tranne il codice di esempio più banale) per:

  1. Usa un framework DI come Spring, quindi
  2. Rendilo parte della tua configurazione DI se le tue dipendenze sono singleton, scope scope, scope della sessione o altro.

Questo approccio offre un’architettura disaccoppiata (e quindi flessibile e testabile) in cui utilizzare un singleton è un dettaglio di implementazione facilmente reversibile (a condizione che i singoli che usi siano sicuri, ovviamente).

Considerate davvero perché avete bisogno di un singleton prima di scriverlo. C’è un dibattito quasi religioso sul loro utilizzo che puoi facilmente inciampare se cerchi google singleton in Java.

Personalmente cerco di evitare i singleton il più spesso ansible per molte ragioni, di nuovo la maggior parte delle quali può essere trovata da singoloni googling. Sento che spesso i singleton vengono abusati perché sono facili da capire da tutti, vengono usati come meccanismo per ottenere dati “globali” in un design OO e vengono utilizzati perché è facile aggirare la gestione del ciclo di vita degli oggetti (o davvero pensando a come puoi fare A dall’interno di B). Guarda cose come Inversion of Control (IoC) o Dependency Injection (DI) per un bel middleground.

Se hai davvero bisogno di uno, allora wikipedia ha un buon esempio di una corretta implementazione di un singleton.

Di seguito sono 3 diversi approcci

1) Enum

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

2) Doppio controllo Bloccaggio / caricamento lento

 /** * 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) Metodo statico di fabbrica

 /** * 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 il Framework di spring per gestire i miei singleton. Non impone il “singleton-ness” della class (che non si può fare comunque se ci sono più caricatori di classi coinvolti) ma fornisce un modo davvero semplice per build e configurare diverse fabbriche per creare diversi tipi di oggetti.

Versione 1:

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

Caricamento lento, thread safe con blocco, prestazioni ridotte a causa della synchronized .

Versione 2:

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

Caricamento lento, thread safe con non bloccante, alte prestazioni.

Wikipedia ha alcuni esempi di singleton, anche in Java. L’implementazione di Java 5 sembra abbastanza completa ed è thread-safe (applicato il blocco a doppio controllo).

Se non hai bisogno di caricare pigro, prova semplicemente

 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(); } } 

Se si desidera un caricamento lento e si desidera che Singleton sia sicuro per i thread, provare il modello di verifica doppia

 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(); } } 

Dato che il pattern di double check non è garantito per funzionare (a causa di qualche problema con i compilatori, non ne so più nulla.), Potresti anche provare a sincronizzare l’intero metodo getInstance o creare un registro per tutti i tuoi Singletons.

Direi Enum Singleton

Singleton che usa enum in Java è generalmente un modo per dichiarare enum singleton. Enum singleton può contenere variabili di istanza e metodo di istanza. Per semplicità, si noti inoltre che se si utilizza un metodo di istanza di quello necessario per garantire la sicurezza del thread di quel metodo, se non influisce sullo stato dell’object.

L’uso di un enum è molto facile da implementare e non ha inconvenienti riguardo agli oggetti serializzabili, che devono essere aggirati negli altri modi.

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

È ansible accedervi Singleton.INSTANCE , molto più semplice del metodo getInstance() su Singleton.

1.12 Serializzazione di costanti Enum

Le costanti Enum sono serializzate in modo diverso rispetto agli ordinari oggetti serializzabili o esternalizzabili. La forma serializzata di una costante enum consiste esclusivamente del suo nome; i valori di campo della costante non sono presenti nel modulo. Per serializzare una costante enum, ObjectOutputStream scrive il valore restituito dal metodo del nome della costante enum. Per deserializzare una costante enum, ObjectInputStream legge il nome costante dallo stream; la costante deserializzata viene quindi ottenuta chiamando il metodo java.lang.Enum.valueOf , passando il tipo di enum della costante insieme al nome della costante ricevuta come argomenti. Come altri oggetti serializzabili o esternalizzabili, le costanti enum possono funzionare come target di riferimenti posteriori che appaiono successivamente nel stream di serializzazione.

Il processo di serializzazione delle costanti di writeReplace non può essere personalizzato: qualsiasi metodo writeObject specifico, writeReplace , writeReplace , readResolve e readResolve definiti dai tipi enum vengono ignorati durante la serializzazione e la deserializzazione. Allo stesso modo, tutte le dichiarazioni di campo serialPersistentFields o serialVersionUID vengono ignorate – tutti i tipi di enum hanno un serialVersionUID fisso di 0L . Non è necessario documentare campi serializzabili e dati per tipi di enumerazione, poiché non vi è alcuna variazione nel tipo di dati inviati.

Citato da documenti Oracle

Un altro problema con i Singletons convenzionali è che una volta implementata l’interfaccia Serializable , non rimangono più Singleton perché il metodo readObject() restituisce sempre una nuova istanza come il costruttore in Java. Questo può essere evitato usando readResolve() e scartando l’istanza appena creata sostituendo con singleton come sotto

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

Questo può diventare ancora più complesso se la class Singleton mantiene lo stato, in quanto è necessario renderli transitori, ma con Enum Singleton, la serializzazione è garantita da JVM.


Buona lettura

  1. Singleton Pattern
  2. Enums, Singletons e Deserialization
  3. Bloccaggio a doppia verifica e schema 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"); } } 

È necessario un idioma a doppio controllo se è necessario caricare pigramente la variabile di istanza di una class. Se è necessario caricare una variabile statica o un singleton pigramente, è necessario inizializzare l’ idioma del detentore della domanda .

Inoltre, se il singleton deve essere seriliazbile, tutti gli altri campi devono essere transitori e il metodo readResolve () deve essere implementato per mantenere invariato l’object singleton. In caso contrario, ogni volta che l’object viene deserializzato, verrà creata una nuova istanza dell’object. Quello che readResolve () fa è sostituire il nuovo object letto da readObject (), che ha costretto il nuovo object a essere garbage collection in quanto non vi è alcuna variabile che si riferisca ad esso.

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

Various ways to make singleton object:

  1. As per Joshua Bloch – Enum would be the best.

  2. you can use double check locking also.

  3. Even inner static class can be used.

Enum singleton

The simplest way to implement a Singleton that is thread-safe is using an 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. You’ll see what I mean.


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. Spero che questo ti aiuti.

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.

Esempi di modelli di progettazione GoF nelle librerie principali di 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 classs 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.