2012-12-05 18 views
9

ho 2 opzioni:Singleton e variabile statica pubblica Java

  1. Singleton modello

    class Singleton{ 
        private static Singleton singleton = null; 
    
        public static synchronized Singleton getInstance(){ 
         if(singleton == null){ 
          singleton = new Singleton(); 
         } 
         return singleton; 
        } 
    } 
    
  2. usando un static final campo

    private static final Singleton singleton = new Singleton(); 
    
    public static Singleton getSingleton() { 
        return singleton; 
    } 
    

cosa è la differenza? (singletreadreaded o multithreaded)

Aggiornamenti: Sono a conoscenza di Bill Pugh o del metodo enum. Non sto cercando il modo corretto, ma ho usato solo 1. C'è davvero qualche differenza b/n 1 o 2?

+0

Dopo la domanda aggiornata nessuna differenza. –

+1

questa domanda non ha nulla a che fare con Singleton. chiedi informazioni sull'accesso a un campo statico dal contesto sincronizzato/non sincronizzato. modifica i tag per favore. – Juvanis

+0

@BhavikAmbani Non sono d'accordo poiché la prima opzione bloccherà ogni thread che tenta di ottenere l'istanza e quindi è leggermente meno performante. –

risposta

10

La differenza principale è che con la prima opzione, il singleton verrà inizializzato solo quando viene chiamato getInstance, mentre con la seconda opzione verrà inizializzato non appena viene caricata la classe contenente.

Un terzo (preferito) opzione che è pigro e filo sicura è usare un enum:

public enum Singleton { 
    INSTANCE; 
} 
+0

Il mio errore, in qualche modo, l'ho perso. Ho aggiornato la domanda ora. Inoltre, sono a conoscenza dell'istanza di singleton ENUM, volevo solo sapere la differenza b.w il 2, ma grazie comunque! – Achow

2

V'è una differenza:

Soluzione 1 è un'inizializzazione differita, l'istanza singleton sarà creato sul primo invocano di getInstance

Soluzione 2 è un'inizializzazione ansioso, l'istanza singleton verrà a creare quando le Loades classe

Entrambi sono thread-safe, chiamare il secondo multi-thread è un po 'ingannevole

+1

Beh, non ho inserito il bit multi-thread. È stato modificato ..: P – Achow

1

Quindi, con l'aggiornamento entrambe le opzioni di cui sopra sono thread-safe. Tuttavia l'opzione synchronized richiede che ogni thread che chiama instance acquisisca questo blocco riducendo le prestazioni se ciò viene eseguito molto. Inoltre, l'uso di synchronized a livello di metodo ha il potenziale problema di utilizzare un blocco pubblicamente disponibile (la classe stessa) che quindi se qualche thread acquisisce questo blocco (che potrebbe) si potrebbe finire con deadlock. L'opzione static final è più performante ma non esegue l'inizializzazione pigra del singleton (che potrebbe non essere un problema a seconda del sistema).

Un'altra opzione che permette thread-safe lazy init del Singleton è il seguente:

public class MySingleton{ 
     private static class Builder{ 
      private static final MySingleton instance = new MySingleton(); 
     } 

     public static MySingleton instance(){ 
      return Builder.intance; 
     } 
} 

Questo funziona perché la classe interna statica sarà garantita essere inizializzato prima dell'esecuzione qualsiasi metodo nella classe contenente.

+0

-1 elettore, si preoccupa di chiarire il ragionamento? –

+0

Ho appena riletto la risposta, e non ha il problema che pensavo avesse. Mi dispiace per quello. :) Rimosso il mio -1. La risposta sembra un po 'come l'insalata di parole per me, anche se ... e tocca a malapena la vera differenza (inizializzazione lazy vs eager). Hai menzionato le prestazioni e il blocco, ma quelle non sono la principale differenza. – cHao

-1

L'implementazione di Singleton in Java (se lo si desidera veramente) può essere eseguita in un modo più elegante di quello descritto per l'inizializzazione sia avida che pigra. Controllare the enum way descritto da Joshua Bloch e the SingletonHolder solution proposto rispettivamente da Bill Pugh.

L'articolo di wikipedia è anche un buon inizio per capire il modello e risponde alla tua domanda.

+1

Non risponde alla domanda. Se vuoi suggerire un modo migliore, va bene ... ma almeno rispondi alla domanda che ti viene posta mentre lo fai. – cHao

+0

Sì, hai ragione ... –

2

Le prime soluzioni sembrano essere più pigre, ma in realtà no.

Una classe viene inizializzata quando si accede a un metodo/campo statico per la prima volta.

È probabile che getInstance() sia l'unico metodo/campo statico accessibile pubblicamente della classe. Questo è il punto di singleton.

Quindi la classe viene inizializzata quando qualcuno chiama getInstance() per la prima volta. Ciò significa che le due soluzioni sono essenzialmente le stesse nella pigrizia.

Naturalmente le 2 soluzioni sembrano migliori e offrono prestazioni migliori.

+0

Essere pigro, nessuna istanza di Singleton creata fino a quando getInstance() non viene invocato esplicitamente. La classe sarà ovviamente caricata entrambe le volte. O mi sta sfuggendo qualcosa? – Achow

+1

nella seconda soluzione, l'istanza viene creata solo quando la classe è inizializzata; la classe viene inizializzata solo quando si accede a un metodo/campo statico, cioè quando viene richiamato getInstance(). – irreputable

Problemi correlati