面試中的單例問題

當我興沖沖的帶著筆記答案參加面試時,突然發現面前的面試官顯得很嚴肅而且眉頭緊鎖,不知道是工作太累了,還是說他對今天的面試官不是很滿意。

于是我就勇敢的坐過去在他的面前坐了下來,沒想到第一道題就讓面試官看出了我的水平,因此今天跟大家聊聊面試中單例的問題,希望大家都能了解這塊內容。

在早期的項目代碼中,如果我們想使用類的某個方法,我們基本都會創建一個類的對象實例然后再調用方法,這樣的實現往往在系統內就會存在某個類的大量實例。如此一來,項目框架很難管理大量的對象,而且如果java虛擬機不能及時回收,容易造成內存溢出。

首先我們要明白什么是單例,所謂單例就是說在項目框架內某個類的對象實例只存在一個,任何調用方獲取到的對象實例都是一個,那么很明顯這個類是不能夠被外部直接調用類構造器創建的。

我們先看下一個簡單的單例設計:

上面代碼在單線程是沒有問題的,而且只有當線程調用類的靜態方法時,才會生成類的靜態變量。但是當多線程訪問時,上面代碼是有問題的,會生成多個對象的實例。

那么,我們可以用另外一種方法實現,比如說在類加載時候就初始化對象的實例,這樣后面無論怎么調用類靜態方法都不創建新的實例。還有一種方法,但是會犧牲部分系統性能,意思就是在多線程訪問方法時通過鎖機制讓線程排隊訪問。我們先通過在類方法上加鎖來實現類的單例,比如:

上述方法能實現單例,而且采用的思路是延遲加載,但是執行效率比較低。

之前有看到部分同學使用雙重鎖(Double CheckLock)機制來實現單例模式,一方面需要在實例上加上volatile關鍵字通知操作系統實現線程訪問時內存屏障,然后還需要在方法中通過虛擬機實現的synchronized來同步方法訪問,寫法如下:

反正,我認為上面的實現是比較復雜的,大家需要去了解的知識點比較多,比如volatile ,synchronized,內存屏障。因此我不建議大家用這種方式,可以作為技術了解下還是有好處的,畢竟如果能跟面試官探討到這一步,還是會加一些分的。

如果說我們不考慮服務負載問題,在多線程環境下可以預先加載類的靜態實例,當虛擬機加載完成類后就會創建類的靜態變量,甭管你到時用不用,反正給你留在那里。所有線程訪問到的都是同一靜態實例,有人也稱這種方式為餓漢式,具體寫法如下:

上面寫法實現單例也是沒有問題的,但是有些同學就會覺得如果我只是想調用一個類的某個靜態方法,并不想生成它的實例,那有沒有其他方法呢,經過各路大神的指點結合自身的總結,可以使用內部靜態類來實現這個需求。

開發的同學都知道,虛擬機在加載類的過程中一開始并不會初始化類的內部靜態類。如果線程調用內部靜態類時,虛擬機只會初始化一次,這樣既可以實現單例,同時也是線程安全的。具體寫法如下:

除了以上講到的幾種方式外,JDK自身的枚舉類型本身就是單例的實現,調用者不能顯式的調用構造器完成實例創建,因此很多Java規范文檔推薦使用枚舉來實現單例。

當然對于初級開發人員而言,現在的主流開發框架都提供單例/多例模式供開發者選擇,這樣的好處讓開發者更多關注業務功能開發,而不用過多關注虛擬機內部類實例創建問題。例如spring中默認類注入就是單例的,可以根據實際情況設置scope為singleton(單例)或者prototype(多例),如下圖所示:

由于本人技術水平還有很大的上升空間,文中存在講述不清楚或者錯誤的地方,請大家批評指正。

歡迎工作一到五年的Java工程師朋友們加入Java架構開發: 854393687

群內提供免費的Java架構學習資料(里面有高可用、高并發、高性能及分布式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.ios高性能編程 (1).內層 最小的內層平均值和峰值(2).耗電量 高效的算法和數據結構(3).初始化時...
    歐辰_OSR閱讀 29,520評論 8 265
  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,135評論 1 32
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,740評論 18 399
  • 轉型,老生常談的問題了,不過今天說的是微商,微商的的本質是什么?周毅認為微商其實就是移動互聯網時代基于社交網絡的移...
    知行圈閱讀 290評論 0 0
  • 小小的卡座,有三個,看起來是挺溫馨,坐在里面喝茶聊天也是一種享受,閑情逸致,喝茶可以讓時間慢下來,習慣了城市的忙碌...
    chen黑子閱讀 133評論 0 0