2017-12-26 12 views
-1

Wie wir für die synchrone Operation beim Erstellen von Singleton-Klasse wissen, machen wir ganze Methode als synchronisiert oder nur Block von Anweisungen, die für die Erstellung von Objekten als synchronisiert verantwortlich sind.Aber, unter diesen beiden Ansätze, die man besser ist und warum?Synchronisierte Methode oder Synchronisierter Block: Welche ist besser beim Schreiben der Singleton-Klasse in Java?

Ansatz 1

public static A getA(){ 
    if (obj == null){ 
     synchronized(Singleton.class) { 
      if (obj == null) { 
       obj = new Singleton();//instance will be created at request time 
      } 
     } 
    } 
    return obj; 
} 

Ansatz 2

public synchronized static A getA(){ 
    if (obj == null){ 
     obj = new Singleton();//instance will be created at request time 
    } 
    return obj; 
} 
+0

es keine Rolle spielt, weil Singletons schlecht sind sowieso –

+1

@SleimanJneidi Einfach nur neugierig, warum Singletons schlecht sind? –

+0

ya ich weiß das, aber, könnten Sie mir bitte erklären, welcher Ansatz unter diesen beiden besser ist? –

Antwort

1

Konzept:

public synchronized static A getA(){ 
    if (obj == null){ 
     obj = new Singleton();//instance will be created at request time 
    } 
    return obj; 
} 

Mit dem Synchronisations Schlüsselwort auf einem Verfahren (wie im Beispiel oben) synchronisiert Zugriff auf das gesamte Verfahren, die in der Regel ziemlich sicher ist, aber es sei denn, Sie haben eine sehr kleine Methode, die Sie Möglicherweise wird ein größerer Teil des Codes synchronisiert, als Sie unbedingt benötigen. Dies ist mehr als erforderlich. Da auf synchronisierte Blöcke/Methoden nur jeweils ein Thread zugreifen kann, verlangsamen sie die Verarbeitung. Je größer ein Stück Code ist, den Sie synchronisieren, desto schlechter ist der Performance-Hit.

Wenn Sie nur eine einzige Ressource erfordern, die faul geladen ist, müssen Sie so etwas wie dies tun:

class MyClass { 
     private static volatile Resource resource; 
     private static final Object LOCK = new Object(); 

     public static Resource getInstance() { 
      if(resource == null) { 
       synchronized(LOCK) { // Add a synch block 
        if(resource == null) { // verify some other synch block didn't 
              // write a resource yet... 
         resource = new Resource(); 
        } 
       } 
      } 
      return resource; 
     } 
} 

Eine wichtige Sache hier die volatile Modifikator für die ganzen Threads in Ihrer App bietet Sichtbarkeit .

1

Die erste ist besser, weil man die Sperre nicht erwerben, wenn obj nicht null ist, während der zweite Ansatz, um die Sperre jedes Mal erwirbt .

1

Ich würde die erste nehmen, die eine doppelt überprüfte Verriegelung hat.

Vielleicht können Sie auch so etwas wie dies versuchen:

public class MySingleton { 
     private static instance = new MySingleton(); 
     private MySingleton(){ } 
     public MySingleton getInstance { 
      return instance; 
     } 
} 
1

Sie würden eine bessere Nutzung Halter Idiom

public class HolderFactory { 
    public static Singleton get() { 
     return Holder.instance; 
    } 

    private static class Holder { 
    public static final Singleton instance = new Singleton(); 
    } 
} 

Es ist faul, weil beispielsweise beim ersten Aufruf von get() erstellt werden, und es ist Thread-sicher, da die Klasse garantiert vom Klassenlader in einem einzelnen Thread geladen wird. Sie könnten auch auf diesen Link, um weitere Informationen überprüfen in Bezug auf Singletons und Thread-Sicherheit: https://shipilev.net/blog/2014/safe-public-construction/

Verwandte Themen