Używam bloku kodu statycznego do zainicjowania niektórych kontrolerów w rejestrze, który mam. Moje pytanie brzmi zatem, czy mogę zagwarantować, że ten statyczny blok kodu zostanie wywołany tylko raz, gdy klasa zostanie po raz pierwszy załadowana? Rozumiem, że nie mogę zagwarantować, kiedy ten blok kodu zostanie wywołany, zgaduję, że kiedy Classloader po raz pierwszy go załaduje. Zdaję sobie sprawę, że mogę zsynchronizować się z klasą w bloku kodu statycznego, ale przypuszczam, że tak właśnie się dzieje?
Prosty przykład kodu byłby;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
czy powinienem to zrobić;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Odpowiedzi:
Tak, statyczne inicjatory Java są bezpieczne dla wątków (użyj pierwszej opcji).
Jeśli jednak chcesz mieć pewność, że kod zostanie wykonany dokładnie raz, musisz upewnić się, że klasa jest ładowana tylko przez jeden program ładujący klasy. Inicjalizacja statyczna jest wykonywana raz na program ładujący klasy.
źródło
To sztuczka, której możesz użyć do leniwej inicjalizacji
lub dla wersji wcześniejszej niż Java 5.0
Ponieważ blok statyczny w SingletonHolder zostanie uruchomiony raz w sposób bezpieczny dla wątków, nie potrzebujesz żadnego innego blokowania. Klasa SingletonHolder zostanie załadowana tylko wtedy, gdy wywołasz instancję ()
źródło
W zwykłych okolicznościach wszystko w statycznym inicjatorze dzieje się przed wszystkim, co używa tej klasy, więc synchronizacja zwykle nie jest konieczna. Jednak klasa jest dostępna dla wszystkiego, co wywołuje statyczny inicjator (w tym powoduje wywoływanie innych statycznych inicjatorów).
Klasa może być ładowana przez klasę załadowaną, ale niekoniecznie jest inicjowana od razu. Oczywiście klasa może być ładowana przez wielokrotne instancje programów ładujących klasy i tym samym stać się wieloma klasami o tej samej nazwie.
źródło
Tak, w pewnym sensie
static
Inicjująca jest wywoływana tylko raz, więc według tej definicji jest to bezpieczne dla wątków - że potrzebne są dwa lub więcej wywołań zstatic
inicjatora nawet dostać wątku rywalizacji.To powiedziawszy,
static
inicjatory są mylące na wiele innych sposobów. Naprawdę nie ma określonej kolejności, w jakiej są wywoływane. Staje się to naprawdę zagmatwane, jeśli masz dwie klasy, którychstatic
inicjatory są od siebie zależne. A jeśli używasz klasy, ale nie używasz tego, costatic
skonfiguruje inicjator, nie masz gwarancji, że program ładujący klasy wywoła inicjator statyczny.Na koniec pamiętaj o obiektach, na których się synchronizujesz. Zdaję sobie sprawę, że tak naprawdę nie o to pytasz, ale upewnij się, że twoje pytanie tak naprawdę nie dotyczy tego, czy musisz zabezpieczyć
addController()
wątki.źródło
Tak, inicjatory statyczne są uruchamiane tylko raz. Przeczytaj to, aby uzyskać więcej informacji .
źródło
Zasadniczo, ponieważ potrzebujesz pojedynczej instancji, powinieneś zrobić to mniej więcej w staroświecki sposób i upewnić się, że obiekt singletona został zainicjowany raz i tylko raz.
źródło