Java中列舉的執行緒安全性及序列化問題
–列舉是如何保證執行緒安全的
要想看原始碼,首先得有一個類吧,那麼列舉型別到底是什麼類呢?是enum嗎?答案很明顯不是,enum就和class一樣,只是一個關鍵字,他並不是一個類,那麼列舉是由什麼類維護的呢,我們簡單的寫一個列舉:
然後我們使用反編譯,看看這段程式碼到底是怎麼實現的,反編譯(Java的反編譯)後程式碼內容如下:
通過反編譯後程式碼我們可以看到,public final class T extends Enum,說明,該類是繼承了Enum類的,同時final關鍵字告訴我們,這個類也是不能被繼承的。當我們使用enmu來定義一個列舉型別的時候,編譯器會自動幫我們建立一個final型別的類繼承Enum類,所以列舉型別不能被繼承,我們看到這個類中有幾個屬性和方法。
我們可以看到:
都是static型別的,因為static型別的屬性會在類被載入之後被初始化,我們在深度分析Java的ClassLoader機制(原始碼級別)和Java類的載入、連結和初始化兩個文章中分別介紹過,當一個Java類第一次被真正使用到的時候靜態資源被初始化、Java類的載入和初始化過程都是執行緒安全的。所以,建立一個enum型別是執行緒安全的。
–為什麼用列舉實現的單例是最好的方式
在單例模式的七種寫法中,我們看到一共有七種實現單例的方式,其中,Effective Java作者Josh Bloch 提倡使用列舉的方式,既然大神說這種方式好,那我們就要知道它為什麼好?
關於這個問題,我有一篇為什麼我牆裂建議大家使用列舉來實現單例。單獨介紹過,這裡再回顧一下。
1. 列舉寫法簡單
寫法簡單這個大家看看單例模式的七種寫法裡面的實現就知道區別了。
你可以通過EasySingleton.INSTANCE來訪問。
2. 列舉自己處理序列化
我們知道,以前的所有的單例模式都有一個比較大的問題,就是一旦實現了Serializable介面之後,就不再是單例得了,因為,每次呼叫 readObject()方法返回的都是一個新建立出來的物件,有一種解決辦法就是使用readResolve()方法來避免此事發生。但是,為了保證列舉型別像Java規範中所說的那樣,每一個列舉型別極其定義的列舉變數在JVM中都是唯一的,在列舉型別的序列化和反序列化上,Java做了特殊的規定。英文原文我就不貼了。
大概意思就是說,在序列化的時候Java僅僅是將列舉物件的name屬性輸出到結果中,反序列化的時候則是通過java.lang.Enum的valueOf方法來根據名字查詢列舉物件。同時,編譯器是不允許任何對這種序列化機制的定製的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。 我們看一下這個valueOf方法:
從程式碼中可以看到,程式碼會嘗試從呼叫enumType這個Class物件的enumConstantDirectory()方法返回的map中獲取名字為name的列舉物件,如果不存在就會丟擲異常。再進一步跟到enumConstantDirectory()方法,就會發現到最後會以反射的方式呼叫enumType這個型別的values()靜態方法,也就是上面我們看到的編譯器為我們建立的那個方法,然後用返回結果填充enumType這個Class物件中的enumConstantDirectory屬性。
所以,JVM對序列化有保證。
3.列舉例項建立是thread-safe(執行緒安全的)
我們在深度分析Java的ClassLoader機制(原始碼級別)和Java類的載入、連結和初始化兩個文章中分別介紹過,當一個Java類第一次被真正使用到的時候靜態資源被初始化、Java類的載入和初始化過程都是執行緒安全的。所以,建立一個enum型別是執行緒安全的。
歡迎工作一到五年的Java工程師朋友們加入Java架構開發:744677563
本群提供免費的學習指導 架構資料 以及免費的解答
不懂得問題都可以在本群提出來 之後還會有職業生涯規劃以及面試指導
相關文章
- 探究Spring中Bean的執行緒安全性問題SpringBean執行緒
- 多執行緒的安全性問題(三)執行緒
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- Spring中多執行緒的使用及問題Spring執行緒
- 多執行緒安全性和Java中的鎖執行緒Java
- 深入解讀HashMap執行緒安全性問題HashMap執行緒
- 深入JAVA執行緒安全問題Java執行緒
- Java 執行緒安全問題的本質Java執行緒
- parallelStream中的執行緒安全問題Parallel執行緒
- 執行緒中斷以及執行緒中斷引發的那些問題執行緒
- 05.java多執行緒問題Java執行緒
- Java多執行緒程式設計中的常見問題及最佳化策略Java執行緒程式設計
- 詳解執行緒池的作用及Java中如何使用執行緒池執行緒Java
- 模板方法中的執行緒安全問題執行緒
- lambda中stream執行緒安全的問題執行緒
- Java中解決多執行緒資料安全問題Java執行緒
- Java中的執行緒Java執行緒
- 執行緒安全性執行緒
- 多執行緒的安全問題及解決方案執行緒
- Java幾種執行緒池及任務佇列Java執行緒佇列
- Json序列化與反序列化導致多執行緒執行速度和單執行緒執行速度一致問題JSON執行緒
- java多執行緒:執行緒池原理、阻塞佇列Java執行緒佇列
- java多執行緒:執行緒同步synchronized(不同步的問題、佇列與鎖),死鎖的產生和解決Java執行緒synchronized佇列
- Java多執行緒面試高配問題---多執行緒(3)🧵Java執行緒面試
- JUC之集合中的執行緒安全問題執行緒
- Python執行緒安全問題及解決方法Python執行緒
- Java中啟動執行緒的方式及區別Java執行緒
- JAVA中執行緒的建立Java執行緒
- Java 中的執行緒 threadJava執行緒thread
- JAVA中的執行緒世界Java執行緒
- Java執行緒的中斷Java執行緒
- Java中的多執行緒Java執行緒
- Java中的執行緒同步Java執行緒
- Java中的執行緒-1Java執行緒
- Java之執行緒安全問題的3種處理方式(通過執行緒同步)Java執行緒
- 二、執行緒安全性執行緒
- 40 個 Java 多執行緒問題總結Java執行緒
- Java多執行緒和併發問題集Java執行緒