Heim  >  Artikel  >  Java  >  Was sind die Unterschiede zwischen Java-Singleton-Mustern?

Was sind die Unterschiede zwischen Java-Singleton-Mustern?

coldplay.xixi
coldplay.xixiOriginal
2020-08-17 14:03:161770Durchsuche

Der Unterschied zwischen dem Java-Singleton-Modus ist: 1. Sobald die Klasse des hungrigen Mannes geladen ist, ist die Singleton-Initialisierung bereits vorhanden, während der faule Mann erst zurückgeht, um den Singleton zu initialisieren, wenn er getInstance aufruft. 2. Der Hungrige Stil ist von Natur aus Thread-sicher, und der Lazy-Stil selbst ist nicht Thread-sicher.

Was sind die Unterschiede zwischen Java-Singleton-Mustern?

[Verwandte Lernempfehlungen: Java-Grundlagen-Tutorial]

Java-Singleton-Modus Der Der Unterschied ist:

1. Lazy Singleton

//懒汉式单例类.在第一次调用的时候实例化自己   
public class Singleton {  
    private Singleton() {}  
    private static Singleton single=null;  
    //静态工厂方法   
    public static Singleton getInstance() {  
         if (single == null) {    
             single = new Singleton();  
         }    
        return single;  
    }  
}

Singleton verhindert den externen Zugriff auf die Klasse, indem es den Konstruktor auf private Instanziierung beschränkt. Im Rahmen derselben virtuellen Maschine kann auf die einzige Instanz von Singleton nur über die Methode getInstance () zugegriffen werden.

(Tatsächlich ist es durch den Java-Reflexionsmechanismus möglich, eine Klasse mit einem privaten Konstruktor zu instanziieren, wodurch grundsätzlich alle Java-Singleton-Implementierungen ungültig werden. Dieses Problem wird hier nicht besprochen. Lassen Sie es uns vorerst verbergen Es wird angenommen, dass der Reflexionsmechanismus nicht vorhanden ist. Die obige Singleton-Implementierung berücksichtigt jedoch keine Thread-Sicherheitsprobleme Gleichzeitige Umgebung: Die folgenden drei Methoden sind alle Modifikationen der getInstance-Methode, um die Thread-Sicherheit von Singletons im Lazy-Stil sicherzustellen Thread-Sicherheit: Sie können zunächst die folgenden drei kleinen Punkte überspringen. Schauen wir uns den Singleton im Hungry-Stil an und gehen Sie dann zurück und betrachten Sie Thread-Sicherheitsprobleme:

1. Synchronisierung zur getInstance-Methode hinzufügen

public static synchronized Singleton getInstance() {  
         if (single == null) {    
             single = new Singleton();  
         }    
        return single;  
}

2. Überprüfen Sie die Sperrung noch einmal

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

3. Statische innere Klasse

public class Singleton {    
    private static class LazyHolder {    
       private static final Singleton INSTANCE = new Singleton();    
    }    
    private Singleton (){}    
    public static final Singleton getInstance() {    
       return LazyHolder.INSTANCE;    
    }    
}

Dies ist besser als die oben genannten 1 und 2. Es erreicht nicht nur Thread-Sicherheit, sondern vermeidet auch die durch die Synchronisierung verursachten Leistungseinbußen.

2. Singleton im Hungry-Stil

//饿汉式单例类.在类初始化时,已经自行实例化   
public class Singleton1 {  
    private Singleton1() {}  
    private static final Singleton1 single = new Singleton1();  
    //静态工厂方法   
    public static Singleton1 getInstance() {  
        return single;  
    }  
}

Hungry-style hat beim Erstellen der Klasse bereits ein statisches Objekt für die Systemverwendung erstellt und wird es in Zukunft nicht ändern . Es ist also von Natur aus Thread-sicher.

3. Registrierter Singleton (kann ignoriert werden)

//类似Spring里面的方法,将类名注册,下次从里面直接获取。  
public class Singleton3 {  
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();  
    static{  
        Singleton3 single = new Singleton3();  
        map.put(single.getClass().getName(), single);  
    }  
    //保护的默认构造子  
    protected Singleton3(){}  
    //静态工厂方法,返还此类惟一的实例  
    public static Singleton3 getInstance(String name) {  
        if(name == null) {  
            name = Singleton3.class.getName();  
            System.out.println("name == null"+"--->name="+name);  
        }  
        if(map.get(name) == null) {  
            try {  
                map.put(name, (Singleton3) Class.forName(name).newInstance());  
            } catch (InstantiationException e) {  
                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                e.printStackTrace();  
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            }  
        }  
        return map.get(name);  
    }  
    //一个示意性的商业方法  
    public String about() {      
        return "Hello, I am RegSingleton.";      
    }      
    public static void main(String[] args) {  
        Singleton3 single3 = Singleton3.getInstance(null);  
        System.out.println(single3.about());  
    }  
}

Der registrierte Singleton verwaltet tatsächlich eine Reihe von Instanzen der Singleton-Klasse und speichert diese Instanzen in einer In the Map ( Bei registrierten Instanzen werden diese direkt aus der Karte zurückgegeben. Bei nicht registrierten Instanzen werden sie zunächst registriert und dann zurückgegeben.

Hier habe ich den Singleton im Registrierungsstil als vernachlässigbar markiert. Erstens wird er aufgrund des statischen Methodenblocks seltener verwendet Darin wird sein Singleton instanziiert, wenn die Klasse geladen wird.

4. Der Unterschied zwischen hungrigem Mann und faulem Mann

In Bezug auf den Namen, hungriger Mann und fauler Mann,

hungriger Mann sind gleich. Nach dem Laden wird der Singleton initialisiert, um sicherzustellen, dass der Singleton bereits vorhanden ist, wenn getInstance aufgerufen wird.

Der faule Mann ist faul und geht erst dann zurück, um den Singleton zu initialisieren, wenn getInstance aufgerufen wird.

Darüber hinaus werden die folgenden zwei Methoden von den folgenden zwei Punkten unterschieden:

1. Thread-Sicherheit:

Hungry Chinese Style ist von Natur aus Thread-sicher und kann direkt verwendet werden Es gibt keine Probleme mit Multithreading.

Der Lazy-Stil selbst ist nicht threadsicher. Um Thread-Sicherheit zu erreichen, gibt es mehrere Schreibmethoden, nämlich 1, 2 und 3 oben. Diese drei Implementierungen weisen eine schlechte Leistung in Bezug auf Ressourcenbelastung und Leistung auf. Es gibt einige Unterschiede in Aspekten.

2. Ressourcenladung und Leistung:

Der hungrige chinesische Stil instanziiert ein statisches Objekt, wenn die Klasse später verwendet wird, aber es wird eine bestimmte Menge an Speicher beanspruchen Dementsprechend ist die Geschwindigkeit beim ersten Aufruf höher, da seine Ressourcen initialisiert wurden.

Der Lazy-Stil verzögert, wie der Name schon sagt, das Laden und wird erst beim ersten Aufruf des Singletons instanziiert Wenn das Objekt zum ersten Mal aufgerufen wird, muss es initialisiert werden. Wenn viel Arbeit zu erledigen ist, kommt es zu einer gewissen Verzögerung bei der Leistung hungriger chinesischer Stil.

Bei den drei Implementierungen 1, 2 und 3 gibt es einige Unterschiede.

Die erste Variante fügt dem Methodenaufruf eine Synchronisierung hinzu, obwohl sie threadsicher ist, muss sie jedoch jedes Mal synchronisiert werden , was sich auf die Leistung auswirkt, schließlich ist in 99 % der Fälle keine Synchronisierung erforderlich.

Die zweite Methode besteht darin, in getInstance zwei Nullprüfungen durchzuführen, um sicherzustellen, dass die Synchronisierung nur durchgeführt wird, wenn der Singleton für aufgerufen wird Beim ersten Mal ist es daher auch threadsicher und vermeidet jedes Mal den Leistungsverlust der Synchronisierung.

Die dritte Methode verwendet den Klassenlademechanismus, um sicherzustellen, dass beim Initialisieren der Instanz nur ein Thread vorhanden ist. Daher ist sie auch threadsicher. sicher und es gibt keinen Leistungsverlust, daher tendiere ich im Allgemeinen dazu, dieses zu verwenden.

Verwandte Lernempfehlungen: Programmiervideos

Das obige ist der detaillierte Inhalt vonWas sind die Unterschiede zwischen Java-Singleton-Mustern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Was sind Java-Build-Tools?Nächster Artikel:Was sind Java-Build-Tools?