簡介: 單例模式是很是經典的高頻面試題,文章主要闡述單例模式的應用場景、IDEA 環境下的多線程調試方式、保證線程安全的單例模式策略、反射暴力攻擊單例解決方案及原理分析、序列化破壞單例的原理及解決方案、常見的單例模式寫法等方面來全面的解析單列模式的細節。java
單例模式主要包含如下幾種寫法:面試
餓漢式單例是在類加載時候就馬上初始化,而且建立單例對象,有着絕對的線程安全性,由於在線程還未出現以前就已經被建立了,因此不存在訪問線程安全性 數據庫
優勢:安全
缺點:微信
代碼實現:多線程
public class HungrySingleton { private HungrySingleton(){ } private static HungrySingleton hungrySingleton = new HungrySingleton(); public static HungrySingleton getHungrySingleton() { return hungrySingleton; } }
咱們也能夠採用靜態代碼塊來實現:框架
public class HungryStaticSingleton { private static final HungryStaticSingleton hungryStaticSingleton; static { hungryStaticSingleton = new HungryStaticSingleton(); } private HungryStaticSingleton(){ } public static HungryStaticSingleton getHungryStaticSingleton() { return hungryStaticSingleton; } }
上述兩種寫法都很是簡單,餓漢式適用的場景通常是單例對象比較少的狀況,在這基礎上咱們下面看一下性能更優的寫法。
被外部類調用的時候內部類纔會加載,會出現線程安全問題 性能
代碼實現: 測試
實現單例類 LazySimpleSingleton
:編碼
public class LazySimpleSingleton { private LazySimpleSingleton(){} private static LazySimpleSingleton lazySimpleSingleton = null; public static LazySimpleSingleton getLazySimpleSingleton() { if (lazySimpleSingleton == null){ lazySimpleSingleton = new LazySimpleSingleton(); } return lazySimpleSingleton; } }
咱們編寫線程測試類:
public class LazySimpleSingletonTest { public static void main(String[] args) { new Thread(()->{ LazySimpleSingleton lazySimpleSingleton = LazySimpleSingleton.getLazySimpleSingleton(); System.out.println(lazySimpleSingleton); }).start(); new Thread(()->{ LazySimpleSingleton lazySimpleSingleton = LazySimpleSingleton.getLazySimpleSingleton(); System.out.println(lazySimpleSingleton); }).start(); } }
正常狀況下輸出的兩個對象是相同的,也是單例, 可是會存在輸出不一樣的狀況,也就是說出現線程安全問題,這裏咱們用 IDEA
的調試功能來進一步的詳細看看各個線程的執行狀況
用線程模式調試,手動控制線程的執行順序來跟蹤內存的變化狀態。先給線程內容打上斷點:
本文由AnonyStar 發佈,可轉載但需聲明原文出處。
仰慕「優雅編碼的藝術」 堅信熟能生巧,努力改變人生
歡迎關注微信公帳號 :coder簡碼 獲取更多優質文章
更多文章關注筆者博客 : IT簡碼