在java中,enum的线程安全性如何?
在java中,enum的线程安全性如何?我正在使用枚举实现单例(根据布洛赫的有效Java),我应该担心我的单例枚举的线程安全性吗?有没有办法证明或反驳它是线程安全的?
// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
谢谢
在java中,enum的线程安全性如何?我正在使用枚举实现单例(根据布洛赫的有效Java),我应该担心我的单例枚举的线程安全性吗?有没有办法证明或反驳它是线程安全的?
// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
谢谢
正如@Mike所说,枚举的创建保证是线程安全的。但是,添加到枚举类的方法不附带任何线程安全保证。特别是,该方法可以由多个线程并发执行。如果这种方法有副作用(改变某些变量的状态),那么你需要考虑保护它(即,制作它)或其部分。leaveTheBuilding
synchronized
自定义枚举定义可能不是线程安全的。例如
RoleEnum.java:
package com.threadsafe.bad;
public enum RoleEnum {
ADMIN(1),
DEV(2),
HEAD(3);
private Integer value;
private RoleEnum(Integer role){
this.value=role;
}
public static RoleEnum fromIntegerValue(Integer role){
for(RoleEnum x : values()){
if(x.value == role ){
return x;
}
}
return RoleEnum.HEAD;
}
Class<?> buildFromClass;
public void setBuildFromClass(Class<?> classType){
buildFromClass=classType;
}
public Class<?> getBuildFromClass(){
return this.buildFromClass;
}
}
主要.java:
package com.threadsafe.bad;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread threadA = new Thread(){
public void run(){
System.out.println("A started");
RoleEnum role;
role=RoleEnum.fromIntegerValue(1);
System.out.println("A called fromIntegerValue");
role.setBuildFromClass(String.class);
System.out.println("A called setBuildFromClass and start to sleep");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread A: "+role.getBuildFromClass());
}
};
Thread threadB = new Thread(){
public void run(){
System.out.println("B started");
RoleEnum role;
role=RoleEnum.fromIntegerValue(1);
role.setBuildFromClass(Integer.class);
System.out.println("B called fromIntegerValue&setBuildFromClass and Start to sleep");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("B waked up!");
System.out.println("Thread B: "+ role.getBuildFromClass());
}
};
threadA.start();
threadB.start();
}
}
有时输出将是:
B 已启动
B 从IntegerValue&setBuildFromClass调用并开始睡眠
已启动
A 调用自整数值
一个叫做 setBuildFromClass 并开始休眠
线程 A: 类 java.lang.String
B醒了!
Thread B: class java.lang.String <-We expect java.lang.Integer
有时输出将是:
已启动
A 调用自整数值
一个叫做 setBuildFromClass 并开始休眠
B 已启动
B 从IntegerValue&setBuildFromClass调用并开始睡眠
线程 A: 类 java.lang.Integer <-我们期望 java.lang.String
B醒了!
线程 B: 类 java.lang.Integer