gpt4 book ai didi

java:类初始化时对同一个类的静态字段进行初始化

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:48:54 24 4
gpt4 key购买 nike

看起来死锁发生在启动应用程序的过程中。我有 jstack 文件,其中我发现一个线程调用 TariffModelManager. 方法,还有其他多个线程调用 TariffModelManager.getInstance() 方法。TariffModelManager 的代码如下:

public class TariffModelManager{
...
private static final TariffModelManager tariffModelManager = TariffModelManager.getInstance();
...
private static volatile TariffModelManager _instance;

private TariffModelManager(){}

public static TariffModelManager getInstance() {
if(_instance == null) {
synchronized(TariffModelManager.class) {
if(_instance == null) _instance = new TariffModelManager();
}
}
return _instance;
}
...
}

我认为,通过调用 getInstance() 方法来初始化静态字段是一个明显的错误,在该方法中检查了另一个字段 (_instance),代码如下所述,但实际发生了什么?

  1. 类初始化时,静态字段从上到下初始化;
  2. 我们正在尝试初始化“tariffModelManager”字段...
  3. 调用方法 getInstance(),检查 _instance 字段(但它未初始化!);
  4. 然后我们必须执行这个类的构造函数;
  5. 如果_instance字段已经在构造函数中初始化,是否可以在静态字段初始化序列中设置为null?

我的问题不是如何解决这个问题,而是描述这段代码执行时到底发生了什么!

更新: Here我找到了详细的类初始化过程,但仍然不清楚,“tariffModelManager”和“_instance”字段是按什么顺序初始化的。

谢谢!

最佳答案

您可以通过在两个静态字段上放置字段断点来验证发生了什么。

我稍微修改了你的示例:

class TariffModelManager {
private static final TariffModelManager tariffModelManager = TariffModelManager.getInstance();
private static volatile TariffModelManager _instance = new TariffModelManager();

private TariffModelManager() {
System.out.println("From Constructor: " + this);
}

public static TariffModelManager getInstance() {
if (_instance == null) {
synchronized (TariffModelManager.class) {
if (_instance == null) {
_instance = new TariffModelManager();
System.out.println("Creating new instance: " + _instance);
}
}
}
return _instance;
}

public static void main(String[] args) {
TariffModelManager.getInstance();

System.out.println("tariffModelManager: " + TariffModelManager.tariffModelManager);
System.out.println("_instance: " + TariffModelManager._instance);
}
}

这是输出:

From Constructor: TariffModelManager@ea4a92b
Creating new instance: TariffModelManager@ea4a92b
From Constructor: TariffModelManager@3c5a99da
tariffModelManager: TariffModelManager@ea4a92b
_instance: TariffModelManager@3c5a99da

首先初始化静态字段tariffModelManager。当调用 getInstance 方法时,_instance 为 null - 即默认值且尚未初始化。然后在该方法中对其进行初始化,并将值也分配给 tariffModelManager。然后根据静态初始化顺序再次重新初始化:Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.

这很有趣,因为

class TariffModelManager {
private static final TariffModelManager tariffModelManager = _instance;
private static volatile TariffModelManager _instance = new TariffModelManager();

private TariffModelManager() {
System.out.println("From Constructor: " + this);
}

public static TariffModelManager getInstance() {
return _instance;
}
}

是无效的 java,但静态方法为您提供了一种“解决”它的方法(好吧 tariffModelManager 将为 null,不是真正想要的,但仍然可以编译):

class TariffModelManager {
private static final TariffModelManager tariffModelManager = getInstance();
private static volatile TariffModelManager _instance = new TariffModelManager();

private TariffModelManager() {
System.out.println("From Constructor: " + this);
}

public static TariffModelManager getInstance() {
return _instance;
}
}

关于java:类初始化时对同一个类的静态字段进行初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47109752/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com