Java静态初始化器是否线程安全?

我正在使用静态代码块来初始化我在registry中的一些控制器。 所以我的问题是,我可以保证,这个静态代码块将只会被绝对调用一次,当第一次加载类? 我知道我不能保证什么时候这个代码块将被调用,我猜它是什么时候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静态初始化器是线程安全的(使用你的第一个选项)。

但是,如果您想要确保只需要确保该类仅由一个类加载器加载,就会执行该代码。 静态初始化每个类加载器执行一次。

这是一个可以用来延迟初始化的技巧

 enum Singleton { INSTANCE; } 

或预先Java 5.0

 class Singleton { static class SingletonHolder { static final Singleton INSTANCE = new Singleton(); } public static Singleton instance() { return SingletonHolder.INSTANCE; } } 

由于SingletonHolder中的静态块将以线程安全方式运行一次,因此不需要任何其他locking。 SingletonHolder类只会在调用instance()的时候被加载,

通常情况下,静态初始化程序中的所有内容都发生在所有使用该类的东西之前,所以通常不需要同步。 然而,这个类可以被任何静态无知者调用(包括导致其他静态初始者被调用)。

一个类可以被加载的类加载,但不一定要马上初始化。 当然,一个类可以通过类加载器的多个实例加载,从而成为具有相同名称的多个类。

是的,有点

一个静态初始化器只被调用一次,所以通过这个定义它是线程安全的 – 你需要两个或更多的静态初始化器的调用,甚至可以获得线程争用。

也就是说,静态初始化器在许多其他方面都是令人困惑的。 真的没有指定的顺序。 如果你有两个类的静态初始值设定项相互依赖的话,这会变得非常混乱。 如果你使用一个类,但是不使用静态初始化器将会设置的东西,那么你不能保证类加载器将调用静态初始化器。

最后,请记住您正在同步的对象。 我意识到这不是真正你要问,但确保你的问题是不是真的问你是否需要使addController()线程安全。

是的,静态初始化器只运行一次。 阅读此以获取更多信息 。

所以基本上,因为你想要一个单例实例,所以你应该或多或less以老式的方式来做,并且确保你的单例对象只被初始化一次。