wzór Singletona w Javie. leniwa inicjalizacja

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

1.is jest jakaś wada z powyższą implementacją metody getInstance? 2.Jaka jest różnica między tymi dwoma implementacjami.?

public static synchronized MySingleton getInstance() { 
 if (_instance==null) {
  _instance = new MySingleton();
 }

 return _instance;
} 

Widziałem wiele odpowiedzi na temat wzorca Singletona w stackoverflow, ale pytanie, które napisałem, to znać głównie różnicę "synchronizacji" na poziomie metody i bloku w tym konkretnym przypadku.

Author: jruizaranguren, 2010-03-26

6 answers

1.is istnieje wada z powyższą implementacją getInstance metoda?

Nie działa. Możesz skończyć z kilkoma instancjami swojego Singletona.

2.Jaka jest różnica między tymi dwoma implementacjami.?

Drugi działa, ale wymaga synchronizacji, która może spowolnić system, gdy masz dużo dostępu do metody z różnych wątków.

Najprostszy poprawny Realizacja:

public class MySingleton{
    private static final MySingleton _instance = new MySingleton();
    private MySingleton(){}
    public static MySingleton getInstance() { 
        return _instance;
    }
}

Krótszy i lepszy (bezpiecznie serializowalny):

public enum MySingleton{
    INSTANCE;

    // methods go here
}

Leniwa inicjalizacja singletonów jest tematem, który zwraca uwagę w sposób nieproporcjonalny do jego rzeczywistej praktycznej użyteczności(IMO argumentowanie o zawiłościach podwójnie sprawdzonego blokowania, do którego twój przykład jest pierwszym krokiem, to nic innego jak konkurs na szczanie).

W 99% wszystkich przypadków, nie potrzebujesz leniwej inicjalizacji, lub "init when class is first referred" Javy jest wystarczy. W pozostałych 1% przypadków jest to najlepsze rozwiązanie:

public enum MySingleton{
    private MySingleton(){}
    private static class Holder {
         static final MySingleton instance = new MySingleton();
    }
    static MySingleton getInstance() { return Holder.instance; }
}
 27
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-20 09:38:20

1.is istnieje wada z powyższą implementacją getInstance metoda?

Tak, zsynchronizowane słowo kluczowe powinno również zawierać instrukcję if. Jeśli nie, to dwa lub więcej wątków może potencjalnie przedostać się do kodu tworzenia.

2.Jaka jest różnica między tymi dwoma implementacjami.?

Druga implementacja jest poprawna i z mojego punktu widzenia łatwiejsza do zrozumienia.

Za pomocą synchronizacji na poziomie metody dla metody statycznej synchronizuje się na klasie, czyli co zrobiłeś w próbce 1. Użycie synchronized at the method level for an instance metoda synchronizuje się na instancji obiektu.

 5
Author: Adrian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-26 08:35:55

Pierwszy jest wadliwy na dwa sposoby. Jak inni tutaj wspominali, wiele wątków może przejść

if (_instance==null) {

Będą czekać na siebie, aż obiekt zostanie całkowicie skonstruowany, ale wykonają instancję i zastąpią odniesienie w zmiennej.

Druga wada jest nieco bardziej skomplikowana. Jeden wątek może dostać się do konstruktora new MySingleton(), a następnie JVM przełącza się na inny wątek. Inny wątek może sprawdzić zmienną pod kątem null, ale może zawierać odniesienie do częściowo zbudowanego obiektu. Więc drugi wątek działa na częściowo zbudowanym Singletonie, to też nie jest dobre. Należy więc unikać pierwszego wariantu.

Drugi wariant powinien działać dobrze. Nie dbaj zbytnio o wydajność, dopóki nie zidentyfikujesz tego wyraźnie jako blokera. Nowoczesne systemy JVMs mogą zoptymalizować niepotrzebne synchronizacje, więc w prawdziwym kodzie produkcyjnym ta konstrukcja może nigdy nie zaszkodzić wydajności.

 4
Author: Dishayloo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-26 08:49:59

[1]}różne podejścia do leniwych singletonów omówił Bob Lee w lazy Loading Singletons I" right " approach to idiomInitialization on Demand Holder (Iodh) , który wymaga bardzo mało kodu i nie ma narzutu synchronizacji.

static class SingletonHolder {
  static Singleton instance = new Singleton();    
}

public static Singleton getInstance() {
  return SingletonHolder.instance;
}

Bob Lee wyjaśnia również, kiedy chce leniwie załadować singleton(podczas testów i rozwoju). Szczerze mówiąc, nie jestem przekonany, że jest to ogromna korzyść.

 4
Author: Pascal Thivent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-26 09:48:13

Drugi jest bezpieczny dla wątków, ale ma narzut synchronizacji przy każdym wywołaniu, bez względu na to, czy instancja jest skonstruowana, czy nie. Pierwsza opcja ma jedną poważną wadę, że nie ma sprawdzania if (_instance = = null) w zsynchronizowanym bloku, aby zapobiec tworzeniu dwóch instancji.

 2
Author: Petar Minchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-26 08:38:07

Proponuję następującą implementację

public class MySingleTon
{

  private static MySingleton obj;

  //private Constructor
  private MySingleTon()
  {
  }


  public static MySingleTon getInstance()
  {
     if(obj==null)
     {
        synchronized(MySingleTon.class)
        {
         if(obj == null)
         {
             obj = new MySingleTon();
         }
        }
     }
     return obj;    
  }
}
 0
Author: Mohd Farid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-26 10:53:12