Я использую статический блок кода для инициализации некоторых контроллеров в реестре, который у меня есть. Поэтому мой вопрос: могу ли я гарантировать, что этот статический блок кода будет вызываться только один раз при первой загрузке класса? Я понимаю, что не могу гарантировать, когда будет вызван этот блок кода, я предполагаю, что когда Classloader впервые загрузит его. Я понимаю, что могу синхронизироваться с классом в блоке статического кода, но я думаю, что это действительно то, что происходит в любом случае?
Простой пример кода будет;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
или я должен сделать это;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Ответы:
Да, статические инициализаторы Java являются потокобезопасными (используйте ваш первый вариант).
Однако, если вы хотите убедиться, что код выполняется точно один раз, вам нужно убедиться, что класс загружается только одним загрузчиком классов. Статическая инициализация выполняется один раз для каждого загрузчика классов.
источник
Это трюк, который вы можете использовать для ленивой инициализации
или для предварительной Java 5.0
Поскольку статический блок в SingletonHolder будет запускаться один раз в поточно-ориентированном режиме, вам не нужны никакие другие блокировки. Класс SingletonHolder будет загружен только при вызове instance ()
источник
В обычных обстоятельствах все в статическом инициализаторе происходит - до всего, что использует этот класс, поэтому синхронизация обычно не требуется. Тем не менее, класс доступен для всего, что вызывает static intiailiser (в том числе вызывает другие статические инициализаторы).
Класс может быть загружен загруженным классом, но не обязательно инициализируется сразу. Конечно, класс может быть загружен несколькими экземплярами загрузчиков классов и таким образом стать несколькими классами с одинаковыми именами.
источник
Да вроде
static
Инициализатор только вызывается один раз, так что по этому определению это поточно - вам нужны два или более вызовыstatic
инициализаторе даже получить нить раздор.Тем не менее,
static
инициализаторы сбивают с толку во многих других отношениях. Там действительно нет определенного порядка, в котором они называются. Это действительно сбивает с толку, если у вас есть два класса,static
инициализаторы которых зависят друг от друга. И если вы используете класс, но не используете то, чтоstatic
инициализатор настроит, вы не гарантированы, что загрузчик классов вызовет статический инициализатор.Наконец, имейте в виду объекты, с которыми вы синхронизируете. Я понимаю, что на самом деле это не то, что вы спрашиваете, но убедитесь, что ваш вопрос на самом деле не спрашивает, нужно ли вам сделать
addController()
потокобезопасным.источник
Да, статические инициализаторы запускаются только один раз. Прочитайте это для получения дополнительной информации .
источник
Таким образом, в основном, так как вам нужен экземпляр singleton, вы должны сделать это более или менее старомодным способом и убедиться, что ваш объект singleton инициализируется один раз и только один раз.
источник