- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个关于 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...
}
现在是否存在由于垃圾收集器而初始化可能恢复为 FALSE 的情况?我问的原因是,如果是这种情况,我需要针对这种情况采取额外的预防措施。
另外,如果我用枚举表示单例,我对状态使用静态变量还是非静态变量会有影响吗?例如,在这个例子中,有两个变量; 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/
我是一名优秀的程序员,十分优秀!