java枚举是怎样保证线程安全的

  介绍

这篇文章主要介绍java枚举是怎样保证线程安全的,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

<强>前言

写在前面:java SE5提供了一种新的类型java的枚举类型,关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能。本文将深入分析枚举的源码,看一看枚举是怎么实现的,他是如何保证线程安全的,以及为什么用枚举实现的单例是最好的方式。

<强>枚举是如何保证线程安全的

要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,枚举就和类一样,只是一个关键字,他并不是一个类,那么枚举是由什么类维护的呢,我们简单的写一个枚举:

public  enum  t  {   春天、夏天、秋天、冬天;   }

然后我们使用反编译,看看这段代码到底是怎么实现的,反编译(Java的反编译)后代码内容如下:

public  final  class  T  extends 枚举   {   年代,private  T (String  int 我)   {   超级(s, i);   }   public  static  T[],值()   {   在[]T ;   int 我;   T  at1 [];   System.arraycopy (at =,枚举值,美元,0,,at1 =, new  T[小姐:=,at.length],, 0,, i);   return  at1;   }   public  static  T 返回对象的值(String  s)   {   return  (T) Enum.valueOf(演示/T, s);   }   public  static  final  T 弹簧;   public  static  final  T 夏天;   public  static  final  T 秋天;   public  static  final  T 冬天;   private  static  final  T 枚举值[]美元;   静态   {   时间=SPRING  new  T (“SPRING",, 0);   时间=SUMMER  new  T (“SUMMER",, 1);   时间=AUTUMN  new  T (“AUTUMN",, 2);   时间=WINTER  new  T (“WINTER",, 3);   ENUM VALUES 美元;=,(new  T [], {   春天,夏天,秋天,冬天   });   }   }

通过反编译后代码我们可以看的到,公众最终类T扩展枚举,说明,该类是继承了Enum类的,同时最后一关键字告诉我们,这个类也是不能被继承的。当我们使用enmu来定义一个枚举类型的时候,编译器会自动帮我们创建一个最终的类型的类继承Enum类,所以枚举类型不能被继承,我们看到这个类中有几个属性和方法。

我们可以看到:

public  static  final  T 弹簧;   public  static  final  T 夏天;   public  static  final  T 秋天;   public  static  final  T 冬天;   private  static  final  T 枚举值[]美元;   静态   {   时间=SPRING  new  T (“SPRING",, 0);   时间=SUMMER  new  T (“SUMMER",, 1);   时间=AUTUMN  new  T (“AUTUMN",, 2);   时间=WINTER  new  T (“WINTER",, 3);   ENUM VALUES 美元;=,(new  T [], {   春天,夏天,秋天,冬天   });   }

都是静态类型的,因为静态类型的属性会在类被加载之后被初始化,我们在深度分析Java的类加载器机制(源码级别)和Java类的加载,链接和初始化两个文章中分别介绍过,当一个Java类第一次被真正使用到的时候静态资源被初始化,Java类的加载和初始化过程都是线程安全的,所以,创建一个enum类型是线程安全的。

<强>为什么用枚举实现的单例是最好的方式

在[转+注]单例模式的七种写法中,我们看到一共有七种实现单例的方式,其中,有效的Java作者乔什布洛赫提倡使用枚举的方式,既然大神说这种方式好,那我们就要知道它为什么好吗?

<强> 1。枚举写法简单

写法简单这个大家看看[转+注]单例模式的七种写法里面的实现就知道区别了。

public  enum  EasySingleton {   实例;   }

你可以通过EasySingleton.INSTANCE来访问。

<强> 2。枚举自己处理序列化

我们知道,以前的所有的单例模式都有一个比较大的问题,就是一旦实现了可序列化的接口之后,就不再是单例得了,因为,每次调用readObject()方法返回的都是一个新创建出来的对象,有一种解决办法就是使用readResolve()方法来避免此事发生。

java枚举是怎样保证线程安全的