为什么enum枚举实现单例模式天然线程安全?

定义枚举时使用 enum 和 class 一样, 是 Java 中的一个关键字。 就像 class 对应一个 Class 类一样, enum 也对应有一个 Enum 类
通过将定义好的枚举反编译, 我们就能发现, 其实枚举在经过 javac 的编译之后, 会被转换成形如 public final class T extends Enum 的定义。
而且, 枚举中的各个枚举项通过 static 来定义的。 如:

public enum T {
	SPRING,SUMMER,AUTUMN,WINTER;
}

反编译后代码为:

public final class T extends Enum 
{
	//省略部分内容
	public static final T SPRING;
	public static final T SUMMER;
	public static final T AUTUMN;
	public static final T WINTER;
	private static final T ENUM$VALUES[];枚举类型和泛型 < 228
	static
	{
		SPRING = new T("SPRING", 0);
		SUMMER = new T("SUMMER", 1);
		AUTUMN = new T("AUTUMN", 2);
		WINTER = new T("WINTER", 3);
		ENUM$VALUES = (new T[] {
		SPRING, SUMMER, AUTUMN, WINTER
	});
	}
}

1.枚举类型T不可被继承
2.T中所有属性都被 static final 修饰,天然支持多线程,原因如下:

了解 JVM 的类加载机制的朋友应该对这部分比较清楚。 static 类型的属性会在类加载过程初始化, 当一个 Java 类第一次被真正使用到的时候静态资源被初始化、 Java 类的加载和初始化过程都是线程安全的( 因为虚拟机在加载枚举的类的时候, 会使用 ClassLoader 的 loadClass 方法, 而这个方法使用同步代码块保证了线程安全) 。

所以, 创建一个 enum 类型是线程安全的。

也就是说, 我们定义的一个枚举, 在第一次被真正用到的时候, 会被虚拟机加载并初始化, 而这个初始化过程是线程安全的

而我们知道, 解决单例的并发问题, 主要解决的就是初始化过程中的线程安全问题

所以, 由于枚举的以上特性, 枚举实现的单例是天生线程安全的。

同时,enum单例模式也支持序列化/反序列化

在序列化的时候 Java 仅仅是将枚举对象的 name 属性输出到结果中,

反序列化的时候则是通过 java.lang.EnumvalueOf 方法根据名字查找枚举对象

同时, 编译器是不允许任何对这种序列化机制的定制的, 因此禁用了 writeObject、 readObject、 readObjectNoData、 writeReplace 和 readResolve 等方法。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值