java設(shè)計(jì)模式之單例模式

單例模式屬于java設(shè)計(jì)模式的一種倦畅,最常見實(shí)現(xiàn)方式有以下幾種 懶漢、餓漢礁凡、雙重檢查單例庐冯、靜態(tài)內(nèi)部類單例孽亲。

單例模式的特點(diǎn):

1:單例類只能有一個(gè)實(shí)例

2:單例類的唯一實(shí)例化必須由自己完成

3:單例類給其他對象提供唯一實(shí)例

如何保證第一個(gè)和第三個(gè)特點(diǎn)呢->2個(gè)實(shí)例化的對象相等說明是同一實(shí)例化對象

1 public class SingletonTest {

2? ?

3? ? public static void main(String[] args) {

4? ? ? ? Singleton singleton1=Singleton.getInstance();

5? ? ? ? Singleton singleton2=Singleton.getInstance();

6? ? ? ? /*

7? ? ? ? ? * 利用Set的特性檢驗(yàn)2個(gè)對象是同一個(gè)實(shí)例

8? ? ? ? ? * 輸出1代表這兩個(gè)變量代表的同一個(gè)實(shí)例對象

9? ? ? ? ? *

10? ? ? ? ? */

11? ? ? ? Set<Singleton> set=new HashSet<Singleton>();

12? ? ? ? set.add(singleton1);

13? ? ? ? set.add(singleton2);

14? ? ? ? System.out.println("set長度"+set.size());

15? ? ? ? //set長度1

16? ? }

17 }

如何理解第二個(gè)特點(diǎn):單例類是的實(shí)例化必須由自己完成->私有化構(gòu)造器

private Singleton() {

? }

1 package com.innerclass; 2? 3 public class SingletonTest { 4? ? ? 5? ? public static void main(String[] args) { 6? ? ? ? //我們在同包中創(chuàng)建一個(gè)其他類 并嘗試創(chuàng)建Singleton實(shí)例 得的一個(gè)錯(cuò)誤 7? ? ? ? //The constructor Singleton() is not visible 8? ? ? ? //構(gòu)造方法Singleton() 是不可見的 也就是說我們無法創(chuàng)建Singleton的實(shí)例對象 9? ? ? ? Singleton singleton=new Singleton();10? ? ? ? 11? ? }12 }

餓漢式的實(shí)現(xiàn)(餓漢式也就是不管你用不用我都把實(shí)例化創(chuàng)建好放在這里,你需要用的時(shí)候就拿去用)

優(yōu)點(diǎn):始終只有一個(gè)singleton實(shí)例對象 所以線程安全

? ? ? ? ? 在類加載的同時(shí)已經(jīng)創(chuàng)建好一個(gè)靜態(tài)對象展父,調(diào)用時(shí)反應(yīng)速度快

缺點(diǎn):jvm加載類的時(shí)候一定會實(shí)例化返劲,如果一直沒調(diào)用getInstance()方法玲昧,會造成資源的浪費(fèi)。

1 public class Singleton {2? private Singleton() {3? }4? private static Singleton singleton=new Singleton();5? public static Singleton getInstance() {6? ? ? return singleton;7? }8 }

線程安全的懶漢式(何為懶漢也就是按需加載 只有在使用的時(shí)候才對單例類去初始化)

優(yōu)點(diǎn):按需加載篮绿,不會造成資源的浪費(fèi)

缺點(diǎn):無synchronized關(guān)鍵字的單例類會造成線程的不同步

1? private Singleton() { 2? ? ? ? 3? } 4? public static Singleton singleton=null;? 5? public synchronized Singleton getInstance(){ 6? ? ? if(singleton==null) { 7? ? ? ? ? return? new Singleton(); 8? ? ? } 9? ? return singleton;10? }

此處說一下為什么要給getInstance()方法加鎖(實(shí)際意義上是給Singleton.class類類型加鎖孵延,有興趣可以去了解一下)

假設(shè)上面的代碼中沒有?synchronized?關(guān)鍵字

public class Singleton {? private Singleton() {? ? ? ? }? private static Singleton singleton=null;? public static? Singleton getInstance(){? ? ? if(singleton==null) {? ? ? ? ? try {       //假設(shè)線程阻塞情況? ? ? ? ? ? Thread.sleep(100);? ? ? ? ? ? return? new Singleton();? ? ? ? } catch (InterruptedException e) {? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? ? ? ? ? ? }? return singleton;? }? public static void main(String[] args) {? ? ? ? Set singletons=? ? ? ? ? ? ? ? new HashSet();? ? ? ? for (int i = 0; i < 10; i++) {? ? ? ? ? ? singletons.add(Singleton.getInstance());? ? ? ? }? ? ? ? System.out.println(singletons.size());     //10     //說明多線程下懶漢式可能會創(chuàng)建多個(gè)實(shí)例對象}}

這種情況下,線程安全可以保證亲配,但是效率問題受到人的詬病了尘应。因?yàn)榫€程第一次實(shí)例化類之后,往后每次獲取實(shí)例化對象仍然需要去獲取單例類的鎖和釋放鎖吼虎。增加了性能的損耗菩收。于是有了以下2中進(jìn)階方式的單例模式

雙重檢查單例(不同于上一個(gè)懶漢式實(shí)現(xiàn)方式? 只有當(dāng)對象未實(shí)例化的時(shí)候才選擇去加鎖創(chuàng)建唯一實(shí)例,若是對象已初始化直接返回已初始化對象鲸睛,提高了效率)

1 public class Singleton { 2 /** 3? ? ? * 雙重檢查單例 4? ? ? */ 5? private Singleton() { 6? ? ? ? ? ? 7? } 8? private static? volatile? Singleton singleton; 9? public static Singleton getInstance() {10? ? ? if(singleton!=null) {11? ? ? ? ? synchronized (Singleton.class) {12? ? ? ? ? ? if(singleton!=null) {13? ? ? ? ? ? ? ? singleton=new Singleton();14? ? ? ? ? ? }15? ? ? ? }16? ? ? }17? ? ? return singleton;18? }19 }

volatile關(guān)鍵字 在這里不做敘述,有興趣的可以直接去百度它的作用

靜態(tài)內(nèi)部類實(shí)現(xiàn)單例(利用原理是內(nèi)部類的對外不可見性)

public class Singleton {? ? private Singleton() {? ? ? ? ? ? }? ? private static? class SingletonHandler{? ? ? ? private static Singleton singleton=new Singleton();? ? }? ? public Singleton getInstance() {? ? ? ? return SingletonHandler.singleton;? ? }? ? }

推薦大家在多線程開發(fā)中使用雙重檢查單例和靜態(tài)內(nèi)部類單例坡贺,集成了懶漢和餓漢的優(yōu)點(diǎn)官辈。

如何只是單線程沒有線程同步情況的話按照情況選擇懶漢和餓漢式。

學(xué)習(xí)過程中遍坟,如有不對拳亿,請指出。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愿伴,一起剝皮案震驚了整個(gè)濱河市肺魁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌隔节,老刑警劉巖鹅经,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怎诫,居然都是意外死亡瘾晃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門幻妓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹦误,“玉大人,你說我怎么就攤上這事肉津∏恳龋” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵妹沙,是天一觀的道長偶洋。 經(jīng)常有香客問我,道長初烘,這世上最難降的妖魔是什么涡真? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任分俯,我火速辦了婚禮,結(jié)果婚禮上哆料,老公的妹妹穿的比我還像新娘缸剪。我一直安慰自己,他們只是感情好东亦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布杏节。 她就那樣靜靜地躺著,像睡著了一般典阵。 火紅的嫁衣襯著肌膚如雪奋渔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天壮啊,我揣著相機(jī)與錄音嫉鲸,去河邊找鬼。 笑死歹啼,一個(gè)胖子當(dāng)著我的面吹牛玄渗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狸眼,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼藤树,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拓萌?” 一聲冷哼從身側(cè)響起岁钓,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎微王,沒想到半個(gè)月后屡限,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炕倘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年囚霸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片激才。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拓型,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘸恼,到底是詐尸還是另有隱情劣挫,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布东帅,位于F島的核電站压固,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏靠闭。R本人自食惡果不足惜帐我,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一坎炼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拦键,春花似錦谣光、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至媚朦,卻和暖如春氧敢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背询张。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工孙乖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人份氧。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓的圆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親半火。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容