Was ist eine effiziente Methode zum implementieren eines singleton-pattern in Java?
Was ist eine effiziente Methode zum implementieren eines singleton-pattern in Java?
"Was ist eine effiziente Methode zum implementieren eines singleton-pattern in Java?" bitte definieren Sie effizient.
medium.com/@kevalpatel2106/... . Dies ist die komplette Artikel auf, wie zu erreichen, Threads, reflection und Serialisierung Sicherheit in der singleton-Muster. Das ist die gute Quelle, um zu verstehen, die Vorteile und Grenzen der singleton-Klasse.
Als Joshua Bloch weist in Effektive Java-enum singleton ist der beste Weg zu gehen. Hier habe ich kategorisiert die verschiedenen Implementierungen, die lazy/eager etc.
medium.com/@kevalpatel2106/... . Dies ist die komplette Artikel auf, wie zu erreichen, Threads, reflection und Serialisierung Sicherheit in der singleton-Muster. Das ist die gute Quelle, um zu verstehen, die Vorteile und Grenzen der singleton-Klasse.
Als Joshua Bloch weist in Effektive Java-enum singleton ist der beste Weg zu gehen. Hier habe ich kategorisiert die verschiedenen Implementierungen, die lazy/eager etc.
InformationsquelleAutor Riyaz Mohammed Ibrahim | 2008-09-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verwendung einer enum:
Joshua Bloch erläutert dieses Konzept in seinem Effektive Java-Reloaded Vortrag auf der Google I/O 2008: link zum video. Siehe auch Folien 30-32 seiner Präsentation (effective_java_reloaded.pdf):
Edit: Eine online-Angebot von "Effective Java" sagt:
Ich persönlich nicht oft zu finden, die brauchen, um die Nutzung des singleton-Musters direkt. Manchmal benutze ich spring ' s dependency injection mit einem Anwendungskontext enthält, was es bezeichnet als singletons. Meine utility-Klassen sind in der Regel enthalten nur statische Methoden, und ich brauche keine Instanzen von Ihnen.
Hi, Kann mir jemand sagen, wie diese Art von singleton kann verspottet und getestet in test-cases. Ich habe versucht zu tauschen fake singleton-Instanz für diese Art, konnte aber nicht.
Ich denke es macht Sinn, aber ich weiß noch nicht, wie es. Wie würden Sie das erstellen einer singleton, die eine andere Klasse erweitert? Wenn Sie ein enum, das können Sie nicht.
Wenn Sie wollen, dass viel Flexibilität, Sie haben bereits vermasselt durch die Implementierung eines singleton in den ersten Platz. Die Fähigkeit zum erstellen einer unabhängigen Instanz, wenn Sie es brauchen, ist eher unbezahlbar für sich.
InformationsquelleAutor Stephen Denne
Je nach Nutzung gibt es mehrere "richtige" Antworten.
Seit java5 der beste Weg, es zu tun, ist die Verwendung eines enum:
Pre java5, der einfachste Fall ist:
Let ' s go über den code. Erstens wollen Sie die Klasse final. In diesem Fall habe ich die
final
Schlüsselwort, um damit die Benutzer wissen, es ist endgültig. Dann müssen Sie den Konstruktor private zu verhindern, dass Benutzer erstellen Ihre eigenen Foo. Das werfen einer exception aus dem Konstruktor verhindert, dass Benutzer mithilfe von reflektion, erstellen Sie eine zweite Foo. Dann erstellen Sie einprivate static final Foo
Feld zu halten, die einzige Instanz, und einepublic static Foo getInstance()
Methode, um es zurückzugeben. Die Java-Spezifikation stellt sicher, dass der Konstruktor wird nur aufgerufen, wenn die Klasse das erste mal verwendet wird.Wenn man ein sehr großes Objekt oder schwere Konstruktion-code UND auch andere zugängliche statische Methoden oder Felder, die verwendet werden könnten, bevor eine Instanz benötigt wird, dann und nur dann müssen Sie die Verwendung von lazy-Initialisierung.
Können Sie eine
private static class
zum laden der Instanz. Der code würde dann so Aussehen:Da die Linie
private static final Foo INSTANCE = new Foo();
wird nur ausgeführt, wenn die Klasse FooLoader tatsächlich verwendet wird, dieser kümmert sich um die verzögerte Instanziierung und wird Sie garantiert werden, um thread-safe.Wenn Sie wollen auch in der Lage sein serialisiert Objekt, das Sie brauchen, um stellen Sie sicher, dass der Deserialisierung wird nicht eine Kopie erstellen.
Die Methode
readResolve()
wird sicherstellen, dass die einzige Instanz, die zurückgegeben werden, selbst wenn das Objekt serialisiert wurde in einer früheren Ausführung des Programms.> "Erstens, Sie wollen die Klasse endgültig". Könnte mir jemand dies erläutern bitte?
Die deserialisation Schutz komplett gebrochen ist (ich denke, dies ist erwähnt Effektive Java 2nd Ed.).
-1 ist
Dies ist nützlich, wenn Sie Ihre singleton muss Erben von einer Oberklasse. Sie können die enum singleton-Muster in diesem Fall, da enums kann nicht von einem übergeordneten (Sie können Schnittstellen implementieren, obwohl). Zum Beispiel, Google Guava verwendet eine static final-Feld, wenn die enum singleton-Muster ist nicht eine option: code.google.com/p/guava-libraries/source/browse/trunk/guava/src/...
InformationsquelleAutor Roel Spilker
Haftungsausschluss: ich habe nur zusammengefasst alle genial Antworten und schrieb es in meinen Worten.
Während der Implementierung des Singleton-wir haben 2 Optionen
1. Lazy loading
2. Frühzeitige Belastung
Lazy loading Hinzugefügt bit-overhead(viel, um ehrlich zu sein) so verwenden Sie es nur, wenn Sie ein sehr großes Objekt oder schwere Konstruktion-code UND auch andere zugängliche statische Methoden oder Felder, die verwendet werden könnten, bevor eine Instanz benötigt wird, dann und nur dann müssen Sie die Verwendung von lazy-Initialisierung.Ansonsten ist die Wahl eine frühzeitige Belastung ist eine gute Wahl.
Meisten einfache Weise der Implementierung der Singleton ist
Alles ist gut, außer seinem frühen geladen singleton. Sie können versuchen lazy geladen singleton
So weit So gut, aber unser held wird nicht überleben, während die Bekämpfung von allein mit mehreren bösen threads, die wollen viele, viele Beispiel unseres Helden.
So können schützen Sie vor bösen multi-threading
aber es ist nicht genug, um aus Helden, Wirklich!!!!!! Dies ist das beste, was wir können/sollten tun, um zu helfen, unser held,
Dies wird als "Double-Checked Locking idiom". Es ist leicht zu vergessen, die flüchtige Anweisung und schwer zu verstehen, warum es notwendig ist.
Details : http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Nun sind wir sicher böse thread, aber was ist mit dem grausamen-Serialisierung? Wir müssen sicherstellen, dass auch während der de-serialiaztion kein neues Objekt erstellt wird,
Die Methode
readResolve()
wird sicherstellen, dass die einzige Instanz, die zurückgegeben werden, selbst wenn das Objekt serialisiert wurde in einer früheren Ausführung in unserem Programm.Schließlich haben wir Hinzugefügt genug Schutz gegen Fäden und Serialisierung aber unser code ist auf der Suche sperrig und hässlich. Geben wir unserem Helden einen über
Ja, das ist unser sehr gleichen Helden 🙂
Da die Linie
private static final Foo INSTANCE = new Foo();
wird nur ausgeführt, wenn die KlasseFooLoader
tatsächlich verwendet wird, dieser kümmert sich um die verzögerte Instanziierung,ist und Sie garantiert werden, um thread-safe.
Und wir kamen so weit, hier ist der beste Weg, um zu erreichen alles, was wir haben ist die beste Möglichkeit
Welche intern behandelt werden wie
Dass es keine Angst mehr vor der Serialisierung von threads und hässlichen code. Auch ENUMS singleton sind faul initialisiert.
-Joshua Bloch in "Effective Java"
Nun werden Sie vielleicht erkannt haben, warum ENUMS als besten Weg für die Implementierung von Singleton und danke für Eure Geduld 🙂
Aktualisiert es auf meinem blog.
tolle Antwort. eine Letzte Sache, überschreiben die clone-Methode zu werfen Ausnahme.
schöne Erklärungen, die ich wirklich genossen und lernte sehr leicht und ich hoffe, nie vergessen, diese
Im 5. Stück des Codes, den Rückgabetyp readResolve() sollte Objekt.
Eine der besten Antworten die ich je rot auf stackoverflow. Danke!
InformationsquelleAutor xyz
Die Lösung gepostet von Stu Thompson ist gültig in Java5.0 und höher. Aber ich würde es vorziehen, es nicht zu verwenden, weil ich denke, es ist auch fehleranfällig.
Es ist leicht zu vergessen, die flüchtige Anweisung und schwer zu verstehen, warum es notwendig ist. Ohne die volatilen dieser code würde nicht thread-sicher mehr wegen dem double-checked-locking-antipattern. Sehen Sie mehr dazu im Absatz 16.2.4 der Java Concurrency in Practice. Kurz gesagt: Dieses Muster (vor Java5.0 oder ohne die flüchtige Anweisung) zurückkehren könnte, einen Verweis auf die Bar-Objekt, die (noch) in einem fehlerhaften Zustand.
Dieses Muster erfunden wurde, um die performance zu optimieren. Aber das ist wirklich kein echtes Problem mehr. Die folgenden lazy-Initialisierung-code ist schneller und vor allem einfacher zu Lesen.
Oh, das ist offenbar der Ansatz befürwortet, William Pugh, der FindBugz Ruhm.
Die erste Ausgabe von Effektiven Java (copyright 2001) Einzelheiten diesem Muster unter Punkt 48.
Was macht Konstruktor private?
Nicht ganz. Die Instanz wird erstellt, in der Klasse be-phase für BarHolder, die verzögert wird, bis das erste mal benötigt wird. Bar-Konstruktor übergeben werden kann, so kompliziert, wie Sie wollen, aber es wird nicht aufgerufen, bis die ersten
getBar()
. (Und wenngetBar
heißt "zu früh" dann wirst du das gleiche problem, egal wie singleons implementiert sind.) Sie können sehen, die faul laden von Klassen, die von den oben stehenden code hier: pastebin.com/iq2eayiRInformationsquelleAutor Benno Richters
Threadsicherheit in Java 5+:
BEARBEITEN: achten Sie auf die
volatile
modifier hier. 🙂 Es ist wichtig, weil ohne Sie, die anderen threads sind nicht garantiert durch das JMM (Java-Memory-Modell) zu sehen, die änderungen an seinen Wert. Die Synchronisation nicht kümmern, dass-es nur serialisiert Zugriff auf diesen code-block.EDIT 2:
@Bno 's Antwort details der Ansatz empfohlen von Bill Pugh (FindBugs) und ist wohl besser. Bitte Lesen, und Stimme seiner Antwort zu.
Siehe Kommentare von stackoverflow.com/questions/70689/...
Ich denke, es ist wichtig zu erwähnen, über reflection attacks. Wahr ist, dass die meisten Entwickler brauchen nicht zu befürchten, aber es scheint, dass Beispiele wie diese (über Enum-basierten singletons) sollte entweder code schützt gegen multiple Instanziierung, angreift oder einfach einen disclaimer, der angibt, von solchen Möglichkeiten.
Volatile-Schlüsselwort ist hier nicht erforderlich - als Synchronisierung ermöglicht sowohl die gegenseitige Ausgrenzung und memory Sichtbarkeit.
Warum die Mühe mit all dem in Java 5+ ? Mein Verständnis ist, dass die enum-Ansatz bietet sowohl die thread-Sicherheit und lazy initialization. Es ist auch viel einfacher... Außerdem, wenn Sie wollen, um zu vermeiden, ein enum, ich würde immer noch verhindern, dass die nested static class-Ansatz...
InformationsquelleAutor Stu Thompson
Vergessen lazy Initialisierung, es ist zu problematisch. Dies ist die einfachste Lösung:
Effektiv zu faul ist die Initialisierung, da die statische singleton-nicht instanziiert werden, bis die Klasse geladen wird und die Klasse nicht geladen werden, bis es gebraucht wird (das wird über die Zeit Recht, dass Sie zuerst Verweis auf die getInstance () - Methode).
Wenn Eine Klasse nicht geladen, bevor Sie wollen, dass die statisch instanziiert werden, Sie können wickeln Sie die statische eine statische innere Klasse zur Entkopplung der Klasse initialisieren.
ich Stimme dieser Antwort ist die einfachste und Anirudhan, gibt es keine Notwendigkeit zu erklären, dass die Instanz endgültig. Kein anderer thread Zugriff auf die Klasse, während die statischen Elemente werden initialisiert. gewährleistet wird dies durch den compiler, in anderen Worten, alle statischen Initialisierung erfolgt in einer synchronisierten Weise - nur ein thread.
Diesen Ansatz haben eine Einschränkung: Der Konstruktor kann nicht werfen eine Ausnahme.
InformationsquelleAutor Jonathan
Stellen Sie sicher, dass Sie es wirklich brauchen. Google nach "singleton-anti-pattern" zu sehen, einige Argumente gegen Sie. Es gibt nichts grundlegend falsch mit ihm, aber ich nehme an es ist nur ein Mechanismus für die Aufdeckung von einigen globalen Ressource/Daten, so stellen Sie sicher, dass dies der beste Weg. Insbesondere habe ich gefunden, dependency injection mehr nützlich, vor allem, wenn Sie auch mit unit-tests, weil DI können Sie verwenden, verspottet Ressourcen für Testzwecke.
InformationsquelleAutor Neil Burroughs
Ich bin verwirrt durch einige der Antworten, die nahelegen, dass DI als eine alternative zur Verwendung von singletons; diese sind die nicht verwandten Konzepte. Sie können nutzen DI zu injizieren, die entweder singleton oder nicht-singleton (z.B. pro-thread) Instanzen. Zumindest gilt das, wenn Sie Spring 2.x, ich kann nicht sprechen für andere DI-frameworks.
Also meine Antwort an den OP wäre (in alle, aber die meisten trivial-Beispiel-code):
Dieser Ansatz gibt Ihnen eine schöne entkoppelt (und daher flexibel und testbar) Architektur, wo, ob ein singleton ist leicht umkehrbar detail (sofern keine singletons verwenden Sie sind threadsicher, natürlich).
Zu erweitern, dass etwas, sollten Sie ein
TicketNumberer
muss eine einzige Globale Instanz, und wo Sie möchten, schreiben Sie eine KlasseTicketIssuer
enthält eine Zeile codeint ticketNumber = ticketNumberer.nextTicketNumber();
. In der traditionellen singleton denken, die Vorherige Zeile der code müsste so etwas wieTicketNumberer ticketNumberer = TicketNumberer.INSTANCE;
. In DI denken, würde die Klasse über einen Konstruktor verfügen, wiepublic TicketIssuer(TicketNumberer ticketNumberer) { this.ticketNumberer = ticketNumberer; }
.Und es wird jemand anderes problem zu nennen, dass der Konstruktor. Ein DI-framework wäre es mit einer globalen Karte von einer Art; eine handgebaute DI-Architektur würde es tun, weil die app
main
- Methode (oder einer seiner Schergen) würde die Abhängigkeit und dann den Konstruktor aufrufen. Im wesentlichen, die Verwendung einer globalen variable (oder eine Globale Methode) ist nur eine einfache form der gefürchtete service locator pattern, und kann ersetzt werden durch dependency injection, genau wie jede andere Verwendung dieses Musters.Ich bin wirklich verwirrt, warum Menschen 'Angst' das service locator pattern. Ich denke, in den meisten Fällen ist es übertrieben oder nicht erforderlich ist am besten, jedoch gibt es scheinbar nützlich Fällen. Mit kleineren Zahl der params-DI ist definitiv bevorzugt, aber Stell dir mal 20+. Sagen Sie den code nicht strukturiert ist nicht ein gültiges argument, weil manchmal Gruppen von Parametern macht einfach keinen Sinn. Auch von einer Einheit der Perspektive des testens, I don ' T care zum testen den service, der business-Logik, und wenn es codiert rechts, dann wäre dies einfach. Ich habe nur gesehen, dass dieses Bedürfnis in sehr großen Projekten.
InformationsquelleAutor Andrew Swan
Wirklich überlegen, warum Sie benötigen, um eine singleton-vor dem schreiben. Es ist eine quasi-religiöse Debatte über die Verwendung von Ihnen, die können Sie ganz einfach stolpern, wenn Sie google singletons in Java.
Ich persönlich versuchen zu vermeiden, singletons, so oft wie möglich, für viele Gründe, wieder die meisten von denen gefunden werden kann, durch googeln singletons. Ich habe das Gefühl, dass ziemlich oft singletons missbraucht werden, weil Sie einfach zu verstehen für jedermann, Sie sind als ein Mechanismus für die erste "Globale" Daten in ein OO-design, und Sie werden verwendet, weil es leicht zu umgehen, Objekt-lifecycle-management (oder wirklich, darüber nachzudenken, wie Sie tun können, Eine von innen B). Blick auf Dinge wie IoC (Inversion of Control) oder Dependency Injection (DI) für einen schönen middleground.
Wenn Sie wirklich brauchen, dann ist wikipedia ein gutes Beispiel für eine korrekte Umsetzung eines Singletons.
InformationsquelleAutor
Folgenden sind 3 verschiedene Ansätze
1) Enum
2) Double-checked-Locking /Lazy loading
3) Statische Fabrik-Methode
InformationsquelleAutor Abhijit Gaikwad
Ich benutze das Spring-Framework für die Verwaltung meiner singletons. Es spielt nicht die Durchsetzung der "singleton-ness" der Klasse (das können Sie eigentlich nicht jedenfalls, wenn es mehrere class loader beteiligt), sondern bietet eine wirklich einfache Möglichkeit zum erstellen und konfigurieren von verschiedenen Fabriken für die Erstellung von verschiedenen Arten von Objekten.
InformationsquelleAutor Matt
Version 1:
Lazy loading, thread-sicher mit Blockierung, niedrige Leistung, weil der
synchronized
.Version 2:
Lazy loading, thread-sicher mit non-blocking, hohe Leistung.
InformationsquelleAutor coderz
Wikipedia hat einige Beispiele von singletons, auch in Java. Die Java-5 Umsetzung sieht ziemlich vollständig, und ist thread-sicher (double-checked locking angewendet).
InformationsquelleAutor macbirdie
Wenn Sie nicht brauchen, lazy loading, dann versuchen Sie einfach
Wenn Sie möchten, lazy loading und Sie möchten, dass Ihre Singleton werden, um thread-sicher, versuchen Sie die überprüfung der Muster
Als der doppelten Kontrolle-Muster ist nicht garantiert, um zu arbeiten (aufgrund von einigen Problem mit Compiler, ich weiß nichts mehr über, das.), Sie könnten auch versuchen, zu synchronisieren, die ganze getInstance-Methode oder erstellen Sie eine Registrierung für alle Singletons.
Doppel-Kontrolle ist sinnlos, für eine statische. Und warum haben Sie das geschützte clone-Methode der öffentlichkeit?
-1 Ihre version von double-checked locking is broken.
-1 Dies ist nicht thread-sicher.
Auch müssen Sie, um das singleton-variable
volatile
InformationsquelleAutor Aleksi Yrttiaho
Ich würde sagen Enum singleton
Singleton mit enum in Java ist in der Regel Weise zu deklarieren, enum singleton. Enum singleton enthalten können Instanz-Variablen und Instanz-Methode. Der Einfachheit halber beachten Sie auch, dass, wenn Sie eine Instanz-Methode als die Sie benötigen, um thread-Sicherheit der Methode, wenn überhaupt, es auf den Zustand des Objekts.
Die Nutzung einer enum-ist sehr einfach zu implementieren und hat keine Nachteile in Bezug auf serialisierbare Objekte, die umgangen werden kann, in der anderen Weise.
Können Sie darauf zugreifen, indem
Singleton.INSTANCE
, viel einfacher als das aufrufengetInstance()
Methode auf Singleton.Ein weiteres problem mit herkömmlichen Singletons sind, dass, sobald Sie implementieren
Serializable
- Schnittstelle, Sie bleiben nicht länger Singleton, weilreadObject()
- Methode immer wieder eine neue Instanz wie der Konstruktor in Java. Dies kann vermieden werden, indemreadResolve()
und verwerfen, neu erstellte Instanz durch den Austausch mit singleton-wie untenDiese können sogar noch komplexer, wenn die Singleton-Klasse Status beizubehalten, müssen Sie Sie vorübergehend, aber mit in Enum Singleton, Serialisierung ist garantiert durch die JVM.
Gut Lesen
InformationsquelleAutor NullPoiиteя
Vielleicht ein wenig spät, um das Spiel auf diesem, aber es gibt eine Menge von nuance, um die Implementierung eines singleton. Der Halter Muster kann nicht verwendet werden, in vielen Situationen. Und IMO, wenn Sie mit einem flüchtigen - Sie sollten auch lokale Variablen verwenden. Beginnen wir am Anfang und wiederholt das ganze auf das problem. Du wirst sehen, was ich meine.
Den ersten Versuch könnte etwa so Aussehen:
Hier haben wir die MySingleton Klasse, die hat eine private statische member-INSTANZ genannt, und eine öffentliche, statische Methode namens getInstance(). Das erste mal getInstance() aufgerufen wird, die INSTANZ-member null ist. Die Strömung wird dann fallen in der Schöpfung-Zustand und erstellen eine neue Instanz der class MySingleton. Nachfolgende Aufrufe von getInstance() wird feststellen, dass die INSTANZ-variable bereits gesetzt ist, und daher nicht noch einen MySingleton instance. Dies stellt sicher, dass es nur eine Instanz von MySingleton, die gemeinsam unter allen Anrufern von getInstance().
Aber diese Implementierung hat ein problem. Multi-Thread-Anwendungen haben eine race condition bei der Erzeugung der einzigen Instanz. Wenn mehrere threads Treffer der getInstance () - Methode auf (oder um) die gleiche Zeit, Sie werden dabei jeweils die INSTANZ-member als null. Dadurch wird jeder thread erstellen einer neuen MySingleton instance und anschließend die Einstellung der INSTANZ-Mitglied.
Hier haben wir die synchronisierten Schlüsselwort in der Signatur der Methode zum synchronisieren der getInstance () - Methode. Das wird sich sicherlich beheben unsere race-Bedingung. Threads werden jetzt zu blockieren, und geben Sie der Methode eine zu einem Zeitpunkt. Aber es schafft auch ein performance-problem. Nicht nur, dass diese Umsetzung synchronisieren die Erzeugung der einzigen Instanz, er synchronisiert alle Anrufe zu getInstance(), einschließlich liest. Liest nicht synchronisiert werden müssen, da Sie einfach wieder den Wert der INSTANZ an. Da liest den Hauptteil unserer Anrufe (denken Sie daran, die Instanziierung geschieht nur beim ersten Aufruf), wir sind gegen einen unnötigen performance-Einbußen durch das synchronisieren der gesamten Methode.
Hier haben wir verschoben Synchronisierung der Signatur der Methode, zu einem synchronisierten block umschließt, die die Erstellung der MySingleton instance. Aber ist das unser problem zu lösen? Gut, wir sind nicht mehr blockiert liest, aber wir haben einen Schritt rückwärts. Mehrere threads auf die getInstance () - Methode an oder um die gleiche Zeit, und Sie werden alle sehen, die INSTANZ-member als null. Sie werden dann drücken Sie die synchronisierten block, wo man um die Sperre und die Instanz erstellen. Wenn dieser thread beendet den block, die anderen threads werden kämpfen für das Schloss, und nach und nach jeder thread wird fallen durch den block, und erstellen Sie eine neue Instanz unserer Klasse. So wir sind wieder da, wo wir angefangen haben.
Hier geben wir einen weiteren Scheck aus dem INNEREN des Blocks. Wenn die INSTANZ-Mitglied wurde bereits eingestellt, wir werden überspringen Sie die Initialisierung. Das ist double-checked-locking.
Dies löst unser problem der multiplen Instanziierung. Aber nochmals, unsere Lösung stellte eine weitere Herausforderung dar. Andere threads können nicht "sehen", dass die INSTANZ-Mitglied wurde aktualisiert. Dieses ist, weil, wie Java optimiert Arbeitsspeicher-Operationen. Threads kopieren Sie die original-Werte der Variablen aus dem Hauptspeicher in den cache der CPU. Änderungen der Werte werden dann geschrieben, und gelesen, dass die cache. Dies ist ein feature von Java entwickelt, um die Leistung zu optimieren. Aber das schafft ein problem für unsere singleton-Implementierung. Einen zweiten thread in Bearbeitung durch einen anderen CPU-Kern oder, mit einem anderen cache — wird nicht sehen, die änderungen des ersten. Dadurch wird der zweite thread zu sehen, die INSTANZ-member als null zwingen, eine neue Instanz unserer singleton erstellt werden soll.
Wir lösen dies, indem Sie das volatile-Schlüsselwort in der Deklaration der INSTANZ-Mitglied. Das sagt der compiler immer zu Lesen von und schreiben auf Speicher, Arbeitsspeicher, und nicht die CPU-cache.
Aber diese einfache änderung kommt zu einem Preis. Da sind wir unter Umgehung der CPU-cache, werfen wir einen performance-hit jedes mal, wenn wir arbeiten nach dem flüchtigen INSTANZ Mitglied sind — was wir tun 4-mal. Wir überprüfen die Existenz (1 und 2), setzen Sie den Wert (3), und dann wieder den Wert (4). Man könnte argumentieren, dass dieser Pfad die Fransen Fall, da wir nur eine Instanz erstellt beim ersten Aufruf der Methode. Vielleicht einen Leistungseinbruch auf die Schöpfung tolerierbar ist. Aber auch unsere Haupt-use-case, liest, wird sich auf die flüchtige Mitglied zweimal. Einmal, um zu überprüfen Existenz, und wieder, wieder seinen Wert.
Da die performance-Einbußen durch den direkten Betrieb auf den flüchtigen Mitglied, setzen wir eine lokale variable auf den Wert der flüchtigen und den Betrieb auf die lokalen Variablen statt. Dies verringert die Anzahl der Zeiten, die wir betreiben, die auf das flüchtige, wodurch die Rückeroberung einige unserer verlorenen Leistung. Beachten Sie, dass wir haben, um unsere lokalen variable wieder, wenn wir geben Sie die synchronisierten block. Dies stellt sicher, es ist up-to-date mit allen änderungen, die aufgetreten, während wir warteten, dass die Schleuse.
Schrieb ich einen Artikel über das kürzlich. Die Dekonstruktion Der Singleton. Sie finden mehr info auf diese Beispiele und ein Beispiel für die "Halter" Muster gibt. Es gibt auch eine real-world-Beispiel präsentiert das double-checked-flüchtigen Ansatz. Hoffe, das hilft.
BearerToken instance
im Artikel ist nichtstatic
? Und was ist esresult.hasExpired()
?Und was ist mit
class MySingleton
– vielleicht sollte esfinal
?Die
BearerToken
Instanz ist nicht statisch, denn es ist Teil derBearerTokenFactory
-, die konfiguriert ist, mit einem bestimmten server erhalten. Es könnte vieleBearerTokenFactory
Objekte - jedes mit einem eigenen "Cache" -BearerToken
, dass Sie die Hände aus, bis es abgelaufen ist. DiehasExpired()
Methode auf dieBeraerToken
heißt in der Fabrikget()
Methode, um sicherzustellen, dass es nicht die hand aus einem abgelaufenen token. Wenn abgelaufen, wird ein neues token angefordert her authorization server. Der Absatz folgenden code-block erklärt diese im detail.InformationsquelleAutor Michael Andrews
wenn sage ich 'eager loading', sagte ich eifrig-Initialisierung.Wenn u denken, ist beides das gleiche, dann was ist eager loading.Vielleicht sollten Sie ein Buch schreiben und korrigieren Sie die Fehler begangen, die von früheren Autoren wie Joshua Bloch.
Effektive Java ist ein tolles Buch, aber auf jeden Fall erfordert die Bearbeitung.
was ist eager loading, u kann beispielsweise zu erklären
Tun Sie etwas "Spannung" bedeutet "so bald wie möglich". Zum Beispiel Hibernate unterstützt das laden von Beziehungen gespannt, wenn erforderlich, ausdrücklich zu.
InformationsquelleAutor Dheeraj Sachan
Dies ist, wie implementieren Sie eine einfache
singleton
:Dies ist, wie man richtig faul, erstellen Sie Ihre
singleton
:der erste Fall wird zu instanziieren, das singleton, wenn die JVM initialisiert die Klasse, der zweite Fall wird nur instanziieren des singleton beim Aufruf
getInstance()
. Aber in der Tat, wenn Sie don ' T haben keine anderen statischen Methoden in der KlasseSingleton
und Sie rufen nurgetInstance()
es gibt keinen wirklichen Unterschied.InformationsquelleAutor Nicolas Filotto
Müssen Sie überprüfen idiom, wenn Sie laden müssen die Instanz-Variablen einer Klasse träge.
Wenn Sie brauchen, um zu laden eine statische variable oder ein singleton-träge, die Sie benötigen, initilization-on-demand-Halter idiom.
Darüber hinaus, wenn der singleton muss seriliazble, alle anderen Felder werden muss, transient und readResolve () - Methode muss implementiert werden, um das singleton-Objekt-Invarianten. Ansonsten, jedes mal, wenn das Objekt deserialisiert wird, wird eine neue Instanz des Objekts erstellt werden. Was readResolve () " ersetzen, die das neue Objekt Lesen von readObject(), die gezwungen ist, das neue Objekt von der garbage Collection freigegeben, da es keine variable, die sich auf ihn.
InformationsquelleAutor Onur
Verschiedene Möglichkeiten, um singleton-Objekt:
Als pro-Joshua Bloch - Enum wäre das beste.
können Sie überprüfen sperren auch.
Sogar innere statische Klasse verwendet werden kann.
InformationsquelleAutor Shailendra Singh
Enum singleton
Die einfachste Möglichkeit zum implementieren eines Singleton, der thread-safe ist mit einem Enum
Dieser code funktioniert seit der Einführung von Enum in Java 1.5
Double-checked locking
Wenn Sie wollen, um code zu einer "klassischen" singleton, arbeitet in einer multithreaded-Umgebung (ab Java 1.5), sollten Sie diese benutzen.
Dies ist nicht thread-sicher vor 1.5 ist, da die Implementierung von volatile-Schlüsselwort war anders.
Frühen Belastung Singleton (funktioniert auch vor Java 1.5)
Diese Implementierung erzeugt das singleton, wenn die Klasse geladen ist und bietet thread-Sicherheit.
InformationsquelleAutor Dan Moldovan
Für JSE 5.0 und oben nehmen Sie die Enum-Ansatz zu verwenden, ansonsten die statische singleton-holder-Ansatz ( (ein lazy loading-Ansatz beschrieben von Bill Pugh). Letztere Lösung ist auch thread-sicher ohne spezielle Sprachkonstrukte (d.h. flüchtige oder synchronisiert).
InformationsquelleAutor raoadnan
Ein anderes argument, das oft gegen Singletons sind, Ihre Testbarkeit Probleme. Singletons sind nicht leicht mockable für Testzwecke. Wenn dies erweist sich ein problem zu sein, ich mag, um die folgenden geringfügigen änderungen:
Den zusätzlichen
setInstance
Methode können Sie eine mockup-Implementierung der singleton-Klasse während der Tests:Funktioniert das auch mit der frühen Initialisierung Ansätze:
Dies hat den Nachteil, entlarven Sie diese Funktion, um die normale Anwendung zu. Andere Entwickler arbeiten an diesem code könnte versucht sein, verwenden Sie die Methode setInstance zu verändern verändern eine bestimmte Funktion und verändert damit die gesamte Anwendung Verhalten, daher sollte diese Methode enthält mindestens eine gute Warnung es ist javadoc.
Dennoch für die Möglichkeit der mockup-Tests (wenn nötig), diese code-Exposition kann zu einem akzeptablen Preis zu bezahlen.
InformationsquelleAutor user3792852
einfachste singleton-Klasse
Duplikat von das Geschwister-Antwort von Jonathan posted fünf Jahre zuvor. Sehen, dass die Antwort für die interessanten Kommentare.
InformationsquelleAutor rohan kamat
Ich denke immer noch nach java 1.5, enum ist die beste verfügbare singleton-Implementierung verfügbar, da er auch dafür sorgt, dass auch im multi-threaded-Umgebungen - nur eine Instanz erstellt wird.
public enum Singleton{
INSTANCE;
}
und Sie sind fertig !!!
InformationsquelleAutor shikjohari
Haben Sie einen Blick auf diese post.
Beispiele für GoF-Design-Patterns in der Java-core-Bibliotheken
Aus die beste Antwort ist "Singleton" - Abschnitt,
Können Sie auch lernen am Beispiel des Singleton-von der systemeigenen Java-Klassen selbst.
InformationsquelleAutor itiskj
Die besten singleton-Muster, das ich je gesehen habe verwendet der Auftragnehmer-Schnittstelle.
Siehe unten:
InformationsquelleAutor
Manchmal ist ein einfaches "
static Foo foo = new Foo();
" ist nicht genug. Man denke nur an einige grundlegende Daten einfügen, die Sie tun möchten.Auf der anderen Seite müssten Sie die Synchronisierung einer Methode, erzeugt ein Objekt der singleton-variable als solche. Die Synchronisation ist nicht schlecht als solche, aber es kann zu Leistungsproblemen führen oder sperren (in sehr sehr seltenen Fällen mit diesem Beispiel. Die Lösung ist
Nun, was passiert? Die Klasse geladen wird über den class-loader. Direkt nach der Klasse interpretiert wurde aus einem byte-Array, die VM führt den static { } - block. das ist das ganze Geheimnis: Der static-block wird nur einmal aufgerufen, die Zeit der jeweiligen Klasse (name) der gegebenen Paket geladen wird, indem diese eine Klasse loader.
InformationsquelleAutor Georgi
Als wir Hinzugefügt haben, Synchronisiert, keyword-bevor getInstance, wir haben es vermieden, die race-Bedingung in dem Fall, wenn zwei threads aufrufen der getInstance zur gleichen Zeit.
InformationsquelleAutor somenath mukhopadhyay