[java]設計模式之singleton(單例)

來源:互聯網
上載者:User

在日常工作中,有很多個物件,我們只需要一個。比如:線程池, 緩衝,註冊表等。如果製造出多個執行個體,就會導致許多問題,如程式行為異常,資源使用過量等。這就需要對對象的構建進行控制,使其只能產生一個對象。這就是本篇要講的設計模式——singleton(單例)。


單例模式的定義:確保只有一個類只有一個執行個體,並提供一個全域訪問點。


那麼,要如何?單例模式,使得一個類只能產生一個對象呢。請看下面的實現:

public class Singleton {private static Singleton s;private Singleton() {}public static Singleton getInstance() {if (s == null) {s = new Singleton();}return s;}}

你或許已經看懂了上面的代碼。沒錯。我們可以通過將類的建構函式設成private存取權限,這樣其他類就無法隨意建立該類的對象了。然後我們應用一個靜態類對象來作為唯一的一個對象,並作為全域訪問點。


clone()方法

還有一件事值得注意:類的clone()方法。例如, 如果基類實現了cloneable介面的話,子類就應該重寫該方法。防止類的對象被copy,破壞單例特性。當然,在應用中應該靈活運用各種方法來防止clone()的各種情況。


多線程訪問singleton方法

對於上面的實現方法,如果在多線程中被訪問,可能會產生問題。

public class Singleton {private static Singleton s;private Singleton() {}// 如果多個線程同時訪問, 有可能會出現多個執行個體。public static Singleton getInstance() {// 第一次初始化時,多個線程同時執行"if (s == null)",判斷結果都為真,所以都會執行下面的操作:"s = new Singleton()",由此引發多個執行個體的出現。if (s == null) {s = new Singleton();}return s;}}

那麼該如何解決單例模式在多線程程式中的問題呢。

方案1:

將getInstance()變成同步(synchronized)方法,多線程的災難可以輕易解決。

public class Singleton {private static Singleton s;private Singleton() {}public static synchronized Singleton getInstance() {if (s == null) {s = new Singleton();}return s;}}

不推薦該方案。 因為對單例初始化只需要一次,這樣做將會使得每次調用getInstance方法時都會進行同步。對運行效率是極大的累贅。


方案2:

在靜態初始化時建立單例。

public class Singleton {// Early initialization.定義的時候就初始化。private static Singleton s = new Singleton();private Singleton() {}public static Singleton getInstance() {return s;}}


該方法可以保證單例。但我們對程式設計時,通常保持直到使用時才建立對象的原則。


方案3:

用“雙重檢查加鎖”,在getInstance()中減少使用同步。

public class Singleton {private static Singleton singleton;private Singleton() {}public static Singleton getInstance() {if (singleton == null) {synchronized (Singleton.class) {if (singleton == null) {   //必須singleton = new Singleton();}}}return singleton;}}
這樣將只有第一次建立對象時同步,既保證了安全執行緒,同時又保證了執行效率。

有人問為什麼要在synchronized 內再一次判斷if(sinlenton == null),我個人理解是這個原因:

如果兩個線程都執行到了第一個if(singleton == null) 且都為true,這是總有一個線程先進入synchronized (Singleton.class)...部分代碼,並阻塞另一個進入。當第一個進入後並成功建了一個執行個體singleton後,不再阻塞。另一個線程將進入執行synchronized (Singleton.class)...代碼(因為它已經執行了第一個singleton==null 並為true)。如果裡面不再進行判斷,則會再一次建立一個singleton。
所以裡面再一次判斷了一次。


參考:

《head first 設計模式》

http://blog.csdn.net/natee/article/details/4408245#quote

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.