Ich verwende einen statischen Codeblock, um einige Controller in einer Registrierung zu initialisieren, die ich habe. Meine Frage ist daher, kann ich garantieren, dass dieser statische Codeblock beim ersten Laden der Klasse nur einmal unbedingt aufgerufen wird? Ich verstehe, dass ich nicht garantieren kann, wann dieser Codeblock aufgerufen wird. Ich schätze, es ist, wenn der Classloader ihn zum ersten Mal lädt. Mir ist klar, dass ich die Klasse im statischen Codeblock synchronisieren kann, aber ich vermute, dass dies tatsächlich sowieso passiert?
Ein einfaches Codebeispiel wäre;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
oder sollte ich das tun;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Antworten:
Ja, statische Java-Initialisierer sind threadsicher (verwenden Sie Ihre erste Option).
Wenn Sie jedoch sicherstellen möchten, dass der Code genau einmal ausgeführt wird, müssen Sie sicherstellen, dass die Klasse nur von einem einzelnen Klassenladeprogramm geladen wird. Die statische Initialisierung wird einmal pro Klassenladeprogramm durchgeführt.
quelle
Dies ist ein Trick, den Sie für die verzögerte Initialisierung verwenden können
oder für vor Java 5.0
Da der statische Block in SingletonHolder einmal threadsicher ausgeführt wird, benötigen Sie keine weitere Sperre. Die Klasse SingletonHolder wird nur geladen, wenn Sie instance () aufrufen.
quelle
Unter normalen Umständen geschieht alles im statischen Initialisierer - vor allem, was diese Klasse verwendet, sodass normalerweise keine Synchronisierung erforderlich ist. Auf die Klasse kann jedoch auf alles zugegriffen werden, was der statische Intiailiser aufruft (einschließlich des Aufrufs anderer statischer Initialisierer).
Eine Klasse kann von einer geladenen Klasse geladen, aber nicht unbedingt sofort initialisiert werden. Natürlich kann eine Klasse durch mehrere Instanzen von Klassenladeprogrammen geladen werden und dadurch zu mehreren Klassen mit demselben Namen werden.
quelle
Mehr oder weniger
Ein
static
Initialisierer wird nur einmal aufgerufen, daher ist er nach dieser Definition threadsicher - Sie benötigen zwei oder mehr Aufrufe desstatic
Initialisierers, um überhaupt Thread-Konflikte zu erhalten.Das heißt,
static
initializers sind in vielerlei anderer Hinsicht verwirrend. Es gibt wirklich keine festgelegte Reihenfolge, in der sie aufgerufen werden. Dies wird sehr verwirrend, wenn Sie zwei Klassen haben, derenstatic
Initialisierer voneinander abhängen. Wenn Sie eine Klasse verwenden, aber nicht das verwenden, was derstatic
Initialisierer einrichten wird, können Sie nicht garantieren, dass der Klassenlader den statischen Initialisierer aufruft.Denken Sie schließlich an die Objekte, auf denen Sie synchronisieren. Mir ist klar, dass dies nicht wirklich das ist, was Sie fragen, aber stellen Sie sicher, dass Ihre Frage nicht wirklich fragt, ob Sie
addController()
threadsicher machen müssen .quelle
Ja, statische Initialisierer werden nur einmal ausgeführt. Lesen Sie dies für weitere Informationen .
quelle
Da Sie also eine Singleton-Instanz möchten, sollten Sie dies mehr oder weniger auf die altmodische Weise tun und sicherstellen, dass Ihr Singleton-Objekt einmal und nur einmal initialisiert wird.
quelle