設計模式之單例模式

2021-09-12 19:13:59 字數 2440 閱讀 3445

單例模式是日常開發中經常使用的模式之一,需要大家對它有足夠的了解。儘管單例模式理解相對其它模式簡單,但是在一些特殊情況下,實現單例模式也需要特別注意。

用來建立獨一無二的,只有乙個物件例項的類。在實際專案中,單例模式使用非常頻繁,例如:執行緒池、資料庫連線池、快取、日誌物件、spring預設bean物件等。在這些情況下,若使用過多例項,可能會導致系統資源使用過量、資料不一致等問題。

大家可能會問,建立全域性靜態變數也能做到如此效果,為什麼還會出現乙個單例模式呢?沒錯,全域性靜態變數確實可以實現如此效果,可是全域性變數是在程式啟動時就已經建立好物件了,如果該物件占用極大記憶體並且使用相對較少,就會造成記憶體資源浪費。使用單例模式,我們可以在需要的時候才去建立物件並且只例項化一次。

單例模式根據實現方式可以分為兩種:懶漢式和餓漢式。

懶漢式,顧名思義就是使用的時候才會進行例項化,延遲載入。**如下:

public class singleton 

} public static singleton newinstance()

return instance;

}}

使用private修飾構造方法,為了防止該類被例項化。另外建構函式中判斷instance是否為空,是為了防止使用反射強行執行建構函式例項化,違反單例結果。

餓漢式,顧名思義就是一開始就進行例項化。**如下:

public class singleton 

} public static singleton newinstance()

}

大家是不是覺得單例模式特別簡單,其實上述兩種實現方式還是有點問題。以懶漢式來說,newinstance()方法,其中我們判斷instance是否為空,不為空則進行例項化,這段**在單執行緒中執行確實沒有什麼問題,但是在多執行緒環境中,假設現在有兩個執行緒同時判空,那麼兩個執行緒都會進行例項化,這個時候,就是有問題的。下面我們就來簡單介紹一下,多執行緒環境中如何實現單例模式。

餓漢式是在jvm載入該類的時候就會進行例項化,所以它是執行緒安全的。上述實現的懶漢式**,如何解決才能實現執行緒安全的呢?大家首先想到的應該是加鎖,沒錯,最簡單的實現方式是這樣的:

public static synchronized singleton newinstance() 

return instance;

}

採用synchronized同步關鍵字,能夠確保多執行緒執行的時候,只有乙個執行緒能夠真正的進行例項化。這種方式簡單是簡單,可是有不好的地方,當我們第一次呼叫的時候,確實需要同步,但是在以後呼叫的時候,多個執行緒每次只能有乙個執行緒獲得例項,這效能肯定是不好的。

上述我們知道,單純的加鎖會引起效能問題。現在我們思考一下,有沒有一種方式,只會在第一次的時候進行加鎖,以後都不會涉及同步。雙重檢查鎖就是這樣,先判斷物件是否為空,再進行加鎖進行例項化,這樣只會在第一次的時候是同步操作,以後都不會經過鎖操作,避免出現效能問題。**如下:

public static singleton newinstance() }}

return instance;

}

private volatile static singleton singleton;
這是為什麼呢?在instance = new singleton();這一行**中,分為三個步驟:1.分配記憶體空間。2.初始化物件。3.將物件指向分配的記憶體空間。關於這三個步驟,由於2和3兩個步驟之間沒有太大關聯,所以編譯器在執行的時候,可能會進行指令重排,導致2和3執行順序顛倒,引起另外乙個執行緒讀取到還未進行初始化的物件。為了解決這個問題,就必須使用volatile,它會防止指令重排。

上述都是採用加鎖的方式實現執行緒安全,有沒有不使用加鎖的方式呢?肯定有,比如下面我們使用的這兩種方式,

public class singleton 

public static singleton newinstance()

private static class singletonholder

}

這種方式不僅是執行緒安全的,並且是延遲載入的,只有在第一次呼叫newinstance()時,才會建立singleton例項。這裡主要應用了內部類和類的初始化方式,內部類被申明為private,外部類不能對它進行初始化,只能由newinstance()方法進行初始化。這種方式沒有涉及到鎖操作,所以在高併發的情況下效能優越。

列舉的特性應該不用介紹吧,天生就是單例的,所以使用列舉方式,效能也是非常優越的。

public enum singleton 

}

單例模式分為懶漢式和餓漢式。對於頻繁使用的物件,特別是一些佔記憶體較大的物件,使用單例模式可以節約資源,並且由於new操作的次數減少,可以減輕gc的壓力。在多執行緒的環境下,要注意單例模式的執行緒安全。

設計模式之單例模式

前一段時間買了一本秦小波寫的 設計模式之禪 網上對這書的評價很高。現在還沒有看很多,但是有些地方頗有感觸,也並不是所有的地方都能看懂,但是會慢慢研究的。自己對於設計模式的感覺就是乙個字 牛!感覺會23種設計模式並且會熟練運用的人,真的就是大師級的牛人了,設計模式是乙個專案主管或者架構師一定要會的東西...

設計模式之單例模式

package com.xie.singleton public class singleton 提供乙個共有的靜態的入口方法 public static singleton getinstance 懶漢式 延遲載入 提供乙個私有的靜態的成員變數,但不做初始化 private static sing...

設計模式之 單例模式

單例模式 singleton 保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。單例模式 單件模式 使用方法返回唯一的例項 public class singleton private static singleton instance public static singleton geti...