2012-12-05 13 views
9

mam 2 opcje:Singleton i zmienna static public Java

  1. Singleton

    class Singleton{ 
        private static Singleton singleton = null; 
    
        public static synchronized Singleton getInstance(){ 
         if(singleton == null){ 
          singleton = new Singleton(); 
         } 
         return singleton; 
        } 
    } 
    
  2. używając static final pole

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

Jaka jest różnica? (singlethreaded lub multithreaded)

Aktualizacje: wiem o metodzie Bill Pugh lub enum. Nie szukam właściwej drogi, ale użyłem tylko 1. Czy jest jakaś różnica b/w 1 lub 2?

+0

Po zaktualizowanym pytaniu nie ma różnicy. –

+1

to pytanie nie ma nic wspólnego z singleton. pytasz o dostęp do pola statycznego ze zsynchronizowanego/niezsynchronizowanego kontekstu. edytuj znaczniki proszę. – Juvanis

+0

@BhavikAmbani Nie zgadzam się, ponieważ pierwsza opcja zablokuje każdy wątek, który próbuje uzyskać instancję i dlatego jest nieco mniej wydajna. –

Odpowiedz

10

Główna różnica polega na tym, że przy pierwszej opcji singleton zostanie zainicjowany dopiero po wywołaniu getInstance, natomiast z drugą opcją zostanie zainicjowany, gdy tylko zostanie załadowana klasa zawierająca.

trzeci (korzystny) rozwiązaniem, które jest leniwa nić jest bezpieczne użycie wyliczenia:

public enum Singleton { 
    INSTANCE; 
} 
+0

Mój błąd, w jakiś sposób go przegapiłem. Mam teraz zaktualizowane pytanie. Ponadto, zdaję sobie sprawę z instancji ENUM Singleton, chciałem tylko poznać różnicę b.w 2, ale dzięki! – Achow

2

pewna różnica:

Roztwór 1 lazy inicjalizacji pojedyncza przykład zostanie utworzone na pierwszym powołaniem się na getInstance

roztworu 2 jest chętnie inicjalizacji pojedyncza przykład będą tworzyć gdy Loades klasy

Oba są bezpieczne dla wątków, wywołanie drugiego wielowątkowego jest nieco mylące:

+1

Cóż, nie wstawiłem wielowątkowego bitu. Zostałem zmontowany ..: P – Achow

1

Tak więc wraz z aktualizacją obie powyższe opcje są wątkowo bezpieczne. Jednak opcja synchronized wymaga, aby każdy wątek, który wywołuje instance, pozyskał tę blokadę, zmniejszając w ten sposób wydajność, jeśli jest to dużo zrobione. Ponadto, używając metody synchronized na poziomie metody, istnieje potencjalny problem z użyciem publicznie dostępnej blokady (samej klasy), więc jeśli jakikolwiek wątek uzyska tę blokadę (co może), może dojść do impasu. Opcja static final jest bardziej wydajna, ale nie wykonuje leniwej inicjalizacji singletonu (co może nie być problemem w zależności od systemu).

Innym rozwiązaniem, które umożliwia bezpieczny wątku leniwy init z Singleton jest następujący:

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

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

To działa, ponieważ statyczna klasa wewnętrzna jest guarenteed zostać zainicjowany zanim jakikolwiek sposób w zawierającego klasy jest wykonywany.

+0

-1 głosujący, czy wyjaśniać uzasadnienie? –

+0

Właśnie przeczytałem odpowiedź i nie ma problemu, który myślałem. Przepraszam za to. :) Usunięto moje -1. Odpowiedź jest dla mnie nieco podobna do słowa "sałata", ale ... ledwo dotyka rzeczywistej różnicy (leniwa i gorliwa inicjacja). Wspominasz wydajność i blokowanie, ale to nie jest główna różnica. – cHao

-1

Implementacja Singleton w Javie (jeśli naprawdę tego chcesz) może być wykonana w bardziej elegancki sposób, niż opisałeś zarówno dla gorliwej, jak i leniwej inicjalizacji. Sprawdź the enum way opisany przez Joshua Blocha i the SingletonHolder solution zaproponowany przez Billa Pugh odpowiednio.

Artykuł Wikipedii jest również dobrym początkiem do zrozumienia wzorca i odpowiada na twoje pytanie.

+1

Nie odpowiada na pytanie. Jeśli chcesz zaproponować lepszy sposób, to jest w porządku ... ale przynajmniej odpowiedz na zadawane pytanie w tym czasie. – cHao

+0

Tak, masz rację ... –

2

Pierwsze rozwiązania wydają się leniwsze, ale w rzeczywistości nie.

Klasa jest inicjowana, gdy statyczna metoda/pole jest dostępne po raz pierwszy.

Jest prawdopodobne, że getInstance() jest jedyną publicznie dostępną statyczną metodą/polem klasy. To jest punkt singletonu.

Następnie klasa zostaje zainicjowana, gdy ktoś zadzwoni getInstance() po raz pierwszy. Oznacza to, że oba rozwiązania są zasadniczo takie same w lenistwie.

Oczywiście, drugie rozwiązanie wygląda lepiej i działa lepiej.

+0

Lazy being, żadna instancja Singletona nie jest tworzona, dopóki getInstance() nie zostanie jawnie wywołana. Klasa będzie oczywiście załadowana za każdym razem. Czy może czegoś brakuje? – Achow

+1

w drugim rozwiązaniu instancja jest tworzona tylko wtedy, gdy klasa jest inicjowana; klasa jest inicjowana tylko wtedy, gdy uzyskuje się dostęp do statycznej metody/pola, tj. gdy wywoływana jest metoda getInstance(). – irreputable