最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java枚舉是如何保證線程安全的

 更新時(shí)間:2019年06月25日 15:12:43   作者:hollischuang  
這篇文章主要介紹了java枚舉是如何保證線程安全的。Java SE5提供了一種新的類型-Java的枚舉類型,關(guān)鍵字enum可以將一組具名的值的有限集合創(chuàng)建為一種新的類型,而這些具名的值可以作為常規(guī)的程序組件使用,這是一種非常有用的功能。,需要的朋友可以參考下

前言

寫在前面:Java SE5提供了一種新的類型-Java的枚舉類型,關(guān)鍵字enum可以將一組具名的值的有限集合創(chuàng)建為一種新的類型,而這些具名的值可以作為常規(guī)的程序組件使用,這是一種非常有用的功能。本文將深入分析枚舉的源碼,看一看枚舉是怎么實(shí)現(xiàn)的,他是如何保證線程安全的,以及為什么用枚舉實(shí)現(xiàn)的單例是最好的方式。

枚舉是如何保證線程安全的

要想看源碼,首先得有一個(gè)類吧,那么枚舉類型到底是什么類呢?是enum嗎?答案很明顯不是,enum就和class一樣,只是一個(gè)關(guān)鍵字,他并不是一個(gè)類,那么枚舉是由什么類維護(hù)的呢,我們簡(jiǎn)單的寫一個(gè)枚舉:

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

然后我們使用反編譯,看看這段代碼到底是怎么實(shí)現(xiàn)的,反編譯(Java的反編譯)后代碼內(nèi)容如下:

public final class T extends Enum
{
private T(String s, int i)
{
super(s, i);
}
public static T[] values()
{
T at[];
int i;
T at1[];
System.arraycopy(at = ENUM$VALUES, 0, at1 = new T[i = at.length], 0, i);
return at1;
}
public static T valueOf(String s)
{
return (T)Enum.valueOf(demo/T, s);
}
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[];
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
});
}
}

通過(guò)反編譯后代碼我們可以看到,public final class T extends Enum,說(shuō)明,該類是繼承了Enum類的,同時(shí)final關(guān)鍵字告訴我們,這個(gè)類也是不能被繼承的。當(dāng)我們使用enmu來(lái)定義一個(gè)枚舉類型的時(shí)候,編譯器會(huì)自動(dòng)幫我們創(chuàng)建一個(gè)final類型的類繼承Enum類,所以枚舉類型不能被繼承,我們看到這個(gè)類中有幾個(gè)屬性和方法。

我們可以看到:

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[];
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
});
}

都是static類型的,因?yàn)閟tatic類型的屬性會(huì)在類被加載之后被初始化,我們?cè)谏疃确治鯦ava的ClassLoader機(jī)制(源碼級(jí)別)和Java類的加載、鏈接和初始化兩個(gè)文章中分別介紹過(guò),當(dāng)一個(gè)Java類第一次被真正使用到的時(shí)候靜態(tài)資源被初始化、Java類的加載和初始化過(guò)程都是線程安全的。所以,創(chuàng)建一個(gè)enum類型是線程安全的。

為什么用枚舉實(shí)現(xiàn)的單例是最好的方式

在[轉(zhuǎn)+注]單例模式的七種寫法中,我們看到一共有七種實(shí)現(xiàn)單例的方式,其中,Effective Java作者Josh Bloch 提倡使用枚舉的方式,既然大神說(shuō)這種方式好,那我們就要知道它為什么好?

1. 枚舉寫法簡(jiǎn)單

寫法簡(jiǎn)單這個(gè)大家看看[轉(zhuǎn)+注]單例模式的七種寫法里面的實(shí)現(xiàn)就知道區(qū)別了。

public enum EasySingleton{
INSTANCE;
}

你可以通過(guò)EasySingleton.INSTANCE來(lái)訪問(wèn)。

2. 枚舉自己處理序列化

我們知道,以前的所有的單例模式都有一個(gè)比較大的問(wèn)題,就是一旦實(shí)現(xiàn)了Serializable接口之后,就不再是單例得了,因?yàn)?,每次調(diào)用 readObject()方法返回的都是一個(gè)新創(chuàng)建出來(lái)的對(duì)象,有一種解決辦法就是使用readResolve()方法來(lái)避免此事發(fā)生。

但是,**為了保證枚舉類型像Java規(guī)范中所說(shuō)的那樣,每一個(gè)枚舉類型極其定義的枚舉變量在JVM中都是唯一的,在枚舉類型的序列化和反序列化上,Java做了特殊的規(guī)定。原文如下:

Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form. To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java.lang.Enum.valueOf method, passing the constant's enum type along with the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream. The process by which enum constants are serialized cannot be customized: any class-specific writeObject, readObject, readObjectNoData, writeReplace, and readResolve methods defined by enum types are ignored during serialization and deserialization. Similarly, any serialPersistentFields or serialVersionUID field declarations are also ignored--all enum types have a fixedserialVersionUID of 0L. Documenting serializable fields and data for enum types is unnecessary, since there is no variation in the type of data sent.

大概意思就是說(shuō),在序列化的時(shí)候Java僅僅是將枚舉對(duì)象的name屬性輸出到結(jié)果中,反序列化的時(shí)候則是通過(guò)java.lang.Enum的valueOf方法來(lái)根據(jù)名字查找枚舉對(duì)象。

同時(shí),編譯器是不允許任何對(duì)這種序列化機(jī)制的定制的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。 我們看一下這個(gè)valueOf方法:

public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) { 
T result = enumType.enumConstantDirectory().get(name); 
if (result != null) 
return result; 
if (name == null) 
throw new NullPointerException("Name is null"); 
throw new IllegalArgumentException( 
"No enum const " + enumType +"." + name); 
} 

從代碼中可以看到,代碼會(huì)嘗試從調(diào)用enumType這個(gè)Class對(duì)象的enumConstantDirectory()方法返回的map中獲取名字為name的枚舉對(duì)象,如果不存在就會(huì)拋出異常。

再進(jìn)一步跟到enumConstantDirectory()方法,就會(huì)發(fā)現(xiàn)到最后會(huì)以反射的方式調(diào)用enumType這個(gè)類型的values()靜態(tài)方法,也就是上面我們看到的編譯器為我們創(chuàng)建的那個(gè)方法,然后用返回結(jié)果填充enumType這個(gè)Class對(duì)象中的enumConstantDirectory屬性。

所以,JVM對(duì)序列化有保證。

3.枚舉實(shí)例創(chuàng)建是thread-safe(線程安全的)

當(dāng)一個(gè)Java類第一次被真正使用到的時(shí)候靜態(tài)資源被初始化、Java類的加載和初始化過(guò)程都是線程安全的。所以,創(chuàng)建一個(gè)enum類型是線程安全的。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目

    搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目

    本文主要介紹了搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解spring boot整合JMS(ActiveMQ實(shí)現(xiàn))

    詳解spring boot整合JMS(ActiveMQ實(shí)現(xiàn))

    本篇文章主要介紹了詳解spring boot整合JMS(ActiveMQ實(shí)現(xiàn)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • java鎖機(jī)制ReentrantLock源碼實(shí)例分析

    java鎖機(jī)制ReentrantLock源碼實(shí)例分析

    這篇文章主要為大家介紹了java鎖機(jī)制ReentrantLock源碼實(shí)例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Springboot整合SpringSecurity實(shí)現(xiàn)登錄認(rèn)證和鑒權(quán)全過(guò)程

    Springboot整合SpringSecurity實(shí)現(xiàn)登錄認(rèn)證和鑒權(quán)全過(guò)程

    這篇文章主要介紹了Springboot整合SpringSecurity實(shí)現(xiàn)登錄認(rèn)證和鑒權(quán)全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • iReport簡(jiǎn)單使用方法圖文教程

    iReport簡(jiǎn)單使用方法圖文教程

    iReport是一個(gè)能夠創(chuàng)建復(fù)雜報(bào)表的開(kāi)源項(xiàng)目,它100%使用Java語(yǔ)言編寫,是目前全球最為流行的開(kāi)源報(bào)表設(shè)計(jì)器,由于它豐富的圖形界面,你能夠很快的創(chuàng)建出任何一種你想要的報(bào)表
    2021-10-10
  • java制作仿微信錄制小視頻控件

    java制作仿微信錄制小視頻控件

    這篇文章主要介紹了java制作仿微信錄制小視頻控件的代碼,錄制小視頻非常方便,有需要的小伙伴可以參考下。
    2015-04-04
  • json序列化時(shí)忽略值為null的字段2種方式實(shí)例

    json序列化時(shí)忽略值為null的字段2種方式實(shí)例

    這篇文章主要給大家介紹了關(guān)于json序列化時(shí)忽略值為null的字段的2種方式,當(dāng)對(duì)象中某個(gè)字段為null時(shí),我們希望將對(duì)象轉(zhuǎn)換成json時(shí)為null的字段不會(huì)被轉(zhuǎn)換到j(luò)son字符串,里面需要的朋友可以參考下
    2023-10-10
  • Java微服務(wù)的打包問(wèn)題解決

    Java微服務(wù)的打包問(wèn)題解決

    本文主要介紹了Java微服務(wù)的打包問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • SpringAop的依賴注入方式

    SpringAop的依賴注入方式

    文章介紹了Spring框架的依賴注入(DI)和面向切面編程(AOP)的基本概念和實(shí)現(xiàn)方式,Spring通過(guò)IOC容器管理Bean的創(chuàng)建和依賴注入,并提供了多種AOP實(shí)現(xiàn)方式,包括代理機(jī)制和配置選項(xiàng)
    2025-02-02
  • Filter中獲取傳遞參數(shù)方式(解決post請(qǐng)求參數(shù)問(wèn)題)

    Filter中獲取傳遞參數(shù)方式(解決post請(qǐng)求參數(shù)問(wèn)題)

    這篇文章主要介紹了Filter中獲取傳遞參數(shù)方式(解決post請(qǐng)求參數(shù)問(wèn)題),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評(píng)論

景洪市| 沛县| 伊宁县| 神木县| 西华县| 襄樊市| 江达县| 台山市| 商丘市| 达孜县| 揭西县| 万年县| 屏边| 鲁山县| 微山县| 四子王旗| 汕头市| 拉孜县| 双流县| 沙雅县| 宜兴市| 兰考县| 博罗县| 满城县| 正镶白旗| 安平县| 阿巴嘎旗| 若羌县| 哈密市| 略阳县| 米脂县| 黄山市| 永清县| 准格尔旗| 新密市| 菏泽市| 格尔木市| 娄烦县| 睢宁县| 徐闻县| 新河县|