Sto implementando una classe singleton in Java per assicurarsi che non venga creata più di una istanza della classe.Come rendere sicuro un thread di classe singleton?
risposta
Forse il modo migliore è utilizzare un enum con una singola istanza. Questo ha il vantaggio di essere serializzabile e garantire la singleton-ness contro la serializzazione e la riflessione, che nessuna implementazione "diretta" di Singleton fa (privata? Ho una riflessione, deriso in modo derisorio dai tuoi modificatori di accesso!). E 'anche molto semplice da implementare:
public enum Singleton {
INSTANCE;
// fields and methods go here
}
I singleton non sono thread-safe per impostazione predefinita. Il modo comune per creare un singleton consiste nell'avere un metodo factory che gestisca la creazione dell'unica istanza. In questo modo puoi controllare la creazione di istanze.
public class Singleton {
public static final Singleton INSTANCE = new Singleton();
private Singleton() { ... }
}
L'utilizzo di una variabile di istanza statica è preferibile alla classe "Titolare" interna. Se lo desideri, puoi anche rendere privato il membro statico e fornire un metodo per accedervi, ma tutto ciò è aggiungere un'altra chiamata al metodo nello stack.
E' piuttosto dipende da quello che stai cercando di ottenere su ciò che si preferisce - il titolare ti dà un Singleton pigro, la versione più semplice non ti dà lazy loading. –
Sì, lo fa. Java non carica le classi finché non vengono utilizzate per la prima volta. –
Non completamente vero. Li carica quando vengono referenziati per la prima volta, ad es. nella firma del metodo di un'altra classe. – skaffman
Che dire di instanciazione pigra: getInstance() restituisce il singleton o lo crea se è la prima chiamata.
public class MySingleton
{
private static MySingleton instance;
private MySingleton()
{
// construct object . . .
}
// For lazy initialization
public static synchronized MySingleton getInstance()
{
if (instance==null)
{
instance = new MySingleton();
}
return instance;
}
// Remainder of class definition . . .
}
L'istanza pigra non è quasi mai necessaria, e se lo è, Java carica le classi in modo pigramente, quindi creare l'istanza nella dichiarazione in realtà * è * istanza lazy - senza overhead di sincronizzazione (in casi molto rari non è abbastanza pigro e la risposta di skaffman è migliore) . –
Si noti inoltre che questa implementazione sincronizza ogni tentativo di ottenere un riferimento all'istanza. Poiché la maggior parte del codice farà qualcosa di simile: Singleton.getInstance.doSomething(); Singleton.getInstance.doSomethingElse(); L'effetto complessivo sarebbe una sincronizzazione aggiuntiva che limita fortemente la concorrenza senza garanzie di sicurezza del thread in termini di accesso/mutazione membri. –
Il blocco doppio controllo in java è rotto http://www.javaworld.com/jw-02-2001/jw-0209-double.html In breve, questo modo di garantire che questa classe venga istanziata una sola volta può causare problemi di concorrenza difficili da trovare. Non usare mai questo. – Buhb
Il modo migliore per fare un singleton? Usa un enum.
public enum Singleton {
INSTANCE;
public void foo(){ ... }
}
// Usage:
Singleton.INSTANCE.foo();
Si ottiene un sacco di aiuto da parte del VM non solo per evitare la doppia esemplificazione, ma aiuta anche a evitare la corruzione deserializzazione.
Se ti interessa la concorrenza, non utilizzerai lo stato globale condiviso.
Se il singleton detiene l'accumulo di risultati da un singolare problema parallelizzato perché no? Un singleton incarna lo stato globale e, in quanto tale, sarebbe uno scenario di utilizzo equo. –
Esistono diversi casi di utilizzo per le classi rappresentate con una sola istanza condivisa tra i processi.Una webapp tipica ben progettata che usa spring probabilmente avrà un gruppo di classi istanziate in scope singleton, condivise tra i thread worker. – Buhb
+1 per deridere i modificatori di accesso. Lo lol'd. :) – corsiKa