首頁  >  文章  >  Java  >  詳細介紹單例模式

詳細介紹單例模式

王林
王林轉載
2020-08-10 16:29:312526瀏覽

詳細介紹單例模式

首先我們來看看單例模式的定義:

單例模式是Java 中最簡單的設計模式之一,屬於建立型模式,它提供了一種創建物件的最佳方式。單例模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對像被創建。

(推薦教程:java入門教程

為了保證內存中有且僅有一個對象,避免頻繁的創建對象造成對內存的消耗,讓所有需要呼叫這個物件的地方都使用這一個單例物件。

接下來我們來看看單例模式的類型:

1、懶漢式

#懶漢式指的是需要使用的時候才會去建立該單例對象。

懶漢式單例模式實作:

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

對於懶漢式單例實作有一個問題,就是如何確保只建立一個物件?若兩個或多個執行緒同時判斷singleton為空,則會建立多個物件。因此我們需要解決線程安全性問題。

說到執行緒安全想到的就是加鎖了,加鎖無非是在方法或類別物件上加鎖。

//在方法上加锁
public class Singleton {
	private static Singleton singleton;
	private Singleton(){}
	public static synchronized Singleton getInstance() {
    	if (singleton == null) {
        	singleton = new Singleton();
    	}
    return singleton;
	}
}

//在类对象上加锁
public class Singleton {
	private static Singleton singleton;
	private Singleton(){}
	public static Singleton getInstance() {
    synchronized(Singleton.class) {   
        if (singleton == null) {
            singleton = new Singleton();
        }
    }
    return singleton;
	}	
}

這兩個方法,能解決多執行緒同時建立單例物件的問題,但每次取得物件都需要先取得鎖,並發效能差。因此還需要最佳化,最佳化目標為:如果沒有實例化對象,則加鎖創建,如果有實例化對象,則直接返回。

(學習影片推薦:java課程

對於在方法上加鎖,無論是否存在實例化物件都需要加鎖。故我們需要優化的是在類別物件上加鎖。

//DCL单例模式(Double Check + Lock)
public class Singleton {
	//volatite关键词防止指令重排序,下文介绍
	private static volatile Singleton singleton;
	private Singleton(){}
	public static Singleton getInstance() {
	//如果singleton不为空,则直接返回对象,若多个线程发现singleton为空,则进入分支
		if (singleton == null) {
		//多个线程同时争抢一个锁,只有一个线程能成功,其他线程需等待
			synchronized(Singleton.class) {
			//争抢到锁的线程需再次判断singleton是否为空,因为有可能被上个线程实例化了
			//若不为空则实例化,后续线程再进入的时候则直接返回该对象
			//对于之后所有进入该方法的线程则无需获取锁,直接返回对象   
        	if (singleton == null) {
           		singleton = new Singleton();
        	}
    		}
		}
    	return singleton;
	}	
}

上述程式碼中加入了volatile關鍵字防止指令重新排序。

2、餓漢式

餓漢式指的是在類別載入時即建立該單例物件。

餓漢式單例模式實作:

public class Singleton {
	private static final Singleton singleton = new Singleton();
	private Singleton(){
	
	}
	public static Singleton getInstance(){
		return singleton;
	}

總結:

懶漢式:需要時才去實例化對象,在開發中如果對記憶體要求很高即採用懶漢式,在多線程環境下,應該使用DCL單例模式,使用DCL單例模式,解決了並發安全及性能低下的問題,若添加volatile關鍵字還能防止指令重新排序而發生的NPE異常。

餓漢式: 類別載入時就已經實例化對象,如果對記憶體需求不高即採用餓漢式,簡單不易出錯,且沒有任何並發安全與效能問題。

以上是詳細介紹單例模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除