gpt4 book ai didi

Java 枚举垃圾回收和枚举变量差异

转载 作者:行者123 更新时间:2023-11-29 08:27:31 25 4
gpt4 key购买 nike

我有一个关于 java 垃圾回收和枚举类型的问题。假设我有一个这样的枚举:

enum ConnectionHelper {
INSTANCE;

private boolean initialized = false;
private static int someVar;


ConnectionHelper initialize() {
if (!initialized) {
// Do some initialisation...
someVar = 10;

// NOTE: 1
initialized = true;
}
return this;
}
void start() {
// NOTE: 2
if (!initialized) {
throw new IllegalStateException("ConnectionHelper has to be initialized.");
}

// do some work...
}
  1. 现在是否存在由于垃圾收集器而初始化可能恢复为 FALSE 的情况?我问的原因是,如果是这种情况,我需要针对这种情况采取额外的预防措施。

  2. 另外,如果我用枚举表示单例,我对状态使用静态变量还是非静态变量会有影响吗?例如,在这个例子中,有两个变量; someVar 和 initialised,如果 initialized 也是静态的,它会对问题 1 产生影响吗?或者如果两者都是非静态的?

    谢谢!

最佳答案

一般来说,我们可以用“否”来回答所有类型的“垃圾收集器会让这个程序表现得很奇怪”的问题。垃圾收集器的真正目的是透明地清理未使用 对象的内存,而您的程序甚至都不会注意到。产生可观察的行为,例如变量从 true 翻转到 false 绝对超出垃圾收集器允许的操作。

也就是说,您的程序不是线程安全的。如果多个线程在没有额外同步的情况下访问您的 ConnectionHelper,它们可能会感知到不一致的结果,包括看到 initialized 变量的 false 而另一个线程已经看到 true 从外部时钟的角度来看,它在较早的时间,或者看到 true initialized 但仍然没有看到 10< 的值someVar 编写。

解决方法很简单。不要实现多余的惰性初始化。 enum 常量在类初始化期间初始化,这已经是惰性的(如 JLS §12.4.1 中指定的)并由 JVM 确保线程安全(如 JLS §12.4.2 中指定的)。

enum ConnectionHelper {
INSTANCE;
private static final int someVar = 10;
void start() {
// do some work, use the already initialized someVar...
}
}

enum ConnectionHelper {
INSTANCE;
private final int someVar = 10;
void start() {
// do some work, use the already initialized someVar...
}
}

enum ConnectionHelper {
INSTANCE;
private final int someVar;
ConnectionHelper() {
someVar = 10; // as place-holder for more complex initialization
}
void start() {
// do some work, use the already initialized someVar...
}
}

是否声明变量 static 并不重要。

第一个调用start()的线程会进行类的初始化,包括someVar的初始化。如果其他线程在初始化仍在进行时调用该方法,它们将等待它完成。初始化完成后,所有线程都可以使用初始化值执行 start() 方法,不会有任何减速。

关于Java 枚举垃圾回收和枚举变量差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51422303/

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