網站首頁 學習教育 IT科技 金融知識 旅遊規劃 生活小知識 家鄉美食 養生小知識 健身運動 美容百科 遊戲知識 綜合知識
當前位置:趣知科普吧 > 綜合知識 > 

單例怎麼寫

欄目: 綜合知識 / 發佈於: / 人氣:1.14W
1. 這個單例的寫法跟一般的寫法有什麼區別

感覺這麼寫可以防止併發操作導致多次實例化例如以下常規寫法:public class Singleton { private Singleton() {} private static Singleton instance = null; public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}當併發調用Singleton.getInstance()時,可能會讓new Singleton()執行多次;當然改成如下形式也可以避免這種問題:public class Singleton { private Singleton() {} private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; }}。

單例怎麼寫
2. 如何寫一個簡單的單例模式

一、基本的實現思路:

單例的實現主要是透過以下兩個步驟:

1、將該類的構造方法定義爲私有方法,這樣其他處的代碼就無法透過調用該類的構造方法來實例化該類的對象,只有透過該類提供的靜態方法來得到該類的唯一實例;

2、在該類內提供一個靜態方法,當我們調用這個方法時,如果類持有的引用不爲空就返回這個引用,如果類保持的引用爲空就創建該類的實例並將實例的引用賦予該類保持的引用。

二、示範如下:

1、枚舉實現單例:

2、懶漢式線程不安全:

3、懶漢式線程安全:

4、餓漢式:

5、雙重校驗鎖:

6、靜態內部類:

擴展資料:

一、單列模式簡介:

單例模式是設計模式中最簡單的形式之一。這一模式的目的是使得類的一個對象成爲系統中的唯一實例。要實現這一點,可以從客戶端對其進行實例化開始。因此需要用一種只允許生成對象類的唯一實例的機制,“阻止”所有想要生成對象的訪問。使用工廠方法來限制實例化過程。這個方法應該是靜態方法(類方法),因爲讓類的實例去生成另一個唯一實例毫無意義。

二、懶漢與餓漢:

1、懶漢方式:指全局的單例實例在第一次被使用時構建。

2、餓漢方式:指全局的單例實例在類裝載時構建。

三、單例模式的三要點:

1、某個類只能有一個實例。

2、它必須自行創建這個實例。

3、它必須自行向整個系統提供這個實例。

四、優缺點:

1、優點:

①實例控制:單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。

②靈活性:因爲類控制了實例化過程,所以類可以靈活更改實例化過程。

2、缺點:

①開銷:雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以透過使用靜態初始化解決此問題。

②可能的開發混淆:使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因爲可能無法訪問庫原始碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。

③對象生存期:不能解決刪除單個對象的問題。在提供內存管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致實例被取消分配,因爲它包含對該實例的私有引用。在某些語言中(如 C++),其他類可以刪除對象實例,但這樣會導致單例類中出現懸浮引用。

參考資料:百度百科單列模式

3. 單例模式怎麼寫,求一份餓漢式單例 一份懶漢式單例

//懶漢式

public class A{

public static A a = null;

public A(){

}

public A getInstance(){

if(a==null){

return new A();

}

return a;

}

}

//餓漢式

public class A{

public static synchonized A a = new A();//線程安全

public A(){

}

public A getInstance(){

return a;

}

}

所謂餓就是急,無論需不需要先將單例對象給創建了,而懶漢式就是慢,需要的時候再創建,此外還有利用java快取式的,利用內部類實現的單例模式,具體可以參考《清華大學出版社》出版的《研磨設計模式》

4. 如何寫一個簡單的單例模式

單例模式的要點有三個;一是某各類只能有一個實例;二是它必須自行創建這個事例;三是它必須自行向整個系統提供這個實例。

單例模式有以下的特點:

1 單例類只可有一個實例。

2 單例類必須自己創建自己這惟一的實例。

3 單例類必須給所有其他對象提供這一實例。

public class EagerSingleton

{

private static final EagerSingleton m_instance =

new EagerSingleton();

/**

* 私有的默認構造子

*/

private EagerSingleton() { }

/**

* 靜態工廠方法

*/

public static EagerSingleton getInstance()

{

return m_instance;

}

}

在這個類被加載時,靜態變量m_instance 會被初始化,此時類的私有構造子會被調用。這時候,單例類的惟一實例就被創建出來了。

樓主可以具體參閱 閻宏博士的《Java與模式》一書的第十五章

5. 如何正確地寫出單例模式

當被問到要實現一個單例模式時,很多人的第一反應是寫出如下的代碼,包括教科書上也是這樣教我們的。

1234567891011public class Singleton {private static Singleton instance;private Singleton (){}public static Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}}這段代碼簡單明瞭,而且使用了懶加載模式,但是卻存在致命的問題。當有多個線程並行調用 getInstance() 的時候,就會創建多個實例。

也就是說在多線程下不能正常工作。懶漢式,線程安全爲了解決上面的問題,最簡單的方法是將整個 getInstance() 方法設爲同步(synchronized)。

123456public static synchronized Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}雖然做到了線程安全,並且解決了多實例的問題,但是它並不高效。因爲在任何時候只能有一個線程調用 getInstance() 方法。

但是同步操作只需要在第一次調用時才被需要,即第一次創建單例實例對象時。這就引出了雙重檢驗鎖。

雙重檢驗鎖雙重檢驗鎖模式(double checked locking pattern),是一種使用同步塊加鎖的方法。程序員稱其爲雙重檢查鎖,因爲會有兩次檢查 instance == null ,一次是在同步塊外,一次是在同步塊內。

爲什麼在同步塊內還要再檢驗一次?因爲可能會有多個線程一起進入同步塊外的 if,如果在同步塊內不進行二次檢驗的話就會生成多個實例了。12345678910public static Singleton getSingleton () {if (instance == null ) { //Single Checkedsynchronized (Singleton.class) {if (instance == null ) { //Double Checkedinstance = new Singleton();}}}return instance ;}這段代碼看起來很完美,很可惜,它是有問題。

主要在於 instance = new Singleton() 這句,這並非是一個原子操作,事實上在 JVM 中這句話大概做了下面 3 件事情。給 instance 分配內存調用 Singleton 的構造函數來初始化成員變量將instance對象指向分配的內存空間(執行完這步 instance 就爲非 null 了)但是在 JVM 的即時編譯器中存在指令重排序的優化。

也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序可能是 1-2-3 也可能是 1-3-2。如果是後者,則在 3 執行完畢、2 未執行之前,被線程二搶佔了,這時 instance 已經是非 null 了(但卻沒有初始化),所以線程二會直接返回 instance,然後使用,然後順理成章地報錯。

我們只需要將 instance 變量聲明成 volatile 就可以了。12345678910111213141516public class Singleton {private volatile static Singleton instance; //聲明成 volatileprivate Singleton (){}public static Singleton getSingleton () {if (instance == null ) {synchronized (Singleton.class) {if (instance == null ) {instance = new Singleton();}}}return instance;}}有些人認爲使用 volatile 的原因是可見性,也就是可以保證線程在本地不會存有 instance 的副本,每次都是去主內存中讀取。

但其實是不對的。使用 volatile 的主要原因是其另一個特性:禁止指令重排序優化。

也就是說,在 volatile 變量的賦值操作後面會有一個內存屏障(生成的彙編代碼上),讀操作不會被重排序到內存屏障之前。比如上面的例子,取操作必須在執行完 1-2-3 之後或者 1-3-2 之後,不存在執行到 1-3 然後取到值的情況。

從「先行發生原則」的角度理解的話,就是對於一個 volatile 變量的寫操作都先行發生於後面對這個變量的讀操作(這裏的“後面”是時間上的先後順序)。但是特別注意在 Java 5 以前的版本使用了 volatile 的雙檢鎖還是有問題的。

其原因是 Java 5 以前的 JMM (Java 內存模型)是存在缺陷的,即時將變量聲明成 volatile 也不能完全避免重排序,主要是 volatile 變量前後的代碼仍然存在重排序問題。這個 volatile 屏蔽重排序的問題在 Java 5 中才得以修復,所以在這之後纔可以放心使用 volatile。

相信你不會喜歡這種複雜又隱含問題的方式,當然我們有更好的實現線程安全的單例模式的辦法。餓漢式 static final field這種方法非常簡單,因爲單例的實例被聲明成 static 和 final 變量了,在第一次加載類到內存中時就會初始化,所以創建實例本身是線程安全的。

12345678910public class Singleton {//類加載時就初始化private static final Singleton instance = new Singleton();private Singleton (){}public static Singleton getInstance (){return instance;}}這種寫法如果完美的話,就沒必要在囉嗦那麼多雙檢鎖的問題了。缺點是它不是一種懶加載模式(lazy initialization),單例會在加載類後一開始就被初始化,即使客戶端沒有調用 getInstance()方法。

餓漢式的創建方式在一些場景中將無法使用:譬如 Singleton 實例的創建是依賴參數或者配置檔案的,在 getInstance() 之前必須調用某個方法設定參數給它,那樣這種單例寫法就無法使用了。靜態內部類 static nested class我比較傾向於使用靜態內部類的方法,這種方法也是《Effective Java》上所推薦的。

123456789public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance () {return 。

6. java中怎麼寫一個單例的例子,看了許多,就是不會寫.

單例就是把構造方法私有化,在類裏實例化對象,並且給一個共有的能返回這個對象的方法

public class Single{

private Single s = null;

private Single(){

}

public static synchronized Single getS(){

if (s == null) {

s = new Singleton();

}

return s;

}

}

7. 如何正確地寫出單例模式

當被問到要實現一個單例模式時,很多人的第一反應是寫出如下的代碼,包括教科書上也是這樣教我們的。

1234567891011public class Singleton {private static Singleton instance;private Singleton (){}public static Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}}這段代碼簡單明瞭,而且使用了懶加載模式,但是卻存在致命的問題。當有多個線程並行調用 getInstance() 的時候,就會創建多個實例。

也就是說在多線程下不能正常工作。懶漢式,線程安全爲了解決上面的問題,最簡單的方法是將整個 getInstance() 方法設爲同步(synchronized)。

123456public static synchronized Singleton getInstance () {if (instance == null ) {instance = new Singleton();}return instance;}雖然做到了線程安全,並且解決了多實例的問題,但是它並不高效。因爲在任何時候只能有一個線程調用 getInstance() 方法。

但是同步操作只需要在第一次調用時才被需要,即第一次創建單例實例對象時。這就引出了雙重檢驗鎖。

雙重檢驗鎖雙重檢驗鎖模式(double checked locking pattern),是一種使用同步塊加鎖的方法。程序員稱其爲雙重檢查鎖,因爲會有兩次檢查 instance == null ,一次是在同步塊外,一次是在同步塊內。

爲什麼在同步塊內還要再檢驗一次?因爲可能會有多個線程一起進入同步塊外的 if,如果在同步塊內不進行二次檢驗的話就會生成多個實例了。12345678910public static Singleton getSingleton () {if (instance == null ) { //Single Checkedsynchronized (Singleton.class) {if (instance == null ) { //Double Checkedinstance = new Singleton();}}}return instance ;}這段代碼看起來很完美,很可惜,它是有問題。

主要在於 instance = new Singleton() 這句,這並非是一個原子操作,事實上在 JVM 中這句話大概做了下面 3 件事情。給 instance 分配內存調用 Singleton 的構造函數來初始化成員變量將instance對象指向分配的內存空間(執行完這步 instance 就爲非 null 了)但是在 JVM 的即時編譯器中存在指令重排序的優化。

也就是說上面的第二步和第三步的順序是不能保證的,最終的執行順序可能是 1-2-3 也可能是 1-3-2。如果是後者,則在 3 執行完畢、2 未執行之前,被線程二搶佔了,這時 instance 已經是非 null 了(但卻沒有初始化),所以線程二會直接返回 instance,然後使用,然後順理成章地報錯。

我們只需要將 instance 變量聲明成 volatile 就可以了。12345678910111213141516public class Singleton {private volatile static Singleton instance; //聲明成 volatileprivate Singleton (){}public static Singleton getSingleton () {if (instance == null ) {synchronized (Singleton.class) {if (instance == null ) {instance = new Singleton();}}}return instance;}}有些人認爲使用 volatile 的原因是可見性,也就是可以保證線程在本地不會存有 instance 的副本,每次都是去主內存中讀取。

但其實是不對的。使用 volatile 的主要原因是其另一個特性:禁止指令重排序優化。

也就是說,在 volatile 變量的賦值操作後面會有一個內存屏障(生成的彙編代碼上),讀操作不會被重排序到內存屏障之前。比如上面的例子,取操作必須在執行完 1-2-3 之後或者 1-3-2 之後,不存在執行到 1-3 然後取到值的情況。

從「先行發生原則」的角度理解的話,就是對於一個 volatile 變量的寫操作都先行發生於後面對這個變量的讀操作(這裏的“後面”是時間上的先後順序)。但是特別注意在 Java 5 以前的版本使用了 volatile 的雙檢鎖還是有問題的。

其原因是 Java 5 以前的 JMM (Java 內存模型)是存在缺陷的,即時將變量聲明成 volatile 也不能完全避免重排序,主要是 volatile 變量前後的代碼仍然存在重排序問題。這個 volatile 屏蔽重排序的問題在 Java 5 中才得以修復,所以在這之後纔可以放心使用 volatile。

相信你不會喜歡這種複雜又隱含問題的方式,當然我們有更好的實現線程安全的單例模式的辦法。餓漢式 static final field這種方法非常簡單,因爲單例的實例被聲明成 static 和 final 變量了,在第一次加載類到內存中時就會初始化,所以創建實例本身是線程安全的。

12345678910public class Singleton {//類加載時就初始化private static final Singleton instance = new Singleton();private Singleton (){}public static Singleton getInstance (){return instance;}}這種寫法如果完美的話,就沒必要在囉嗦那麼多雙檢鎖的問題了。缺點是它不是一種懶加載模式(lazy initialization),單例會在加載類後一開始就被初始化,即使客戶端沒有調用 getInstance()方法。

餓漢式的創建方式在一些場景中將無法使用:譬如 Singleton 實例的創建是依賴參數或者配置檔案的,在 getInstance() 之前必須調用某個方法設定參數給它,那樣這種單例寫法就無法使用了。靜態內部類 static nested class我比較傾向於使用靜態內部類的方法,這種方法也是《Effective Java》上所推薦的。

123456789public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public 。

8. 如何寫一個單例模式

class Single(object): _instance = None _is_init = False def __new__(cls, *args, **kw): if cls._instance is None: cls._instance = object.__new__(cls, *args, **kw) return cls._instance def __init__(self): if not Single._is_init: # 給對象進行來初始源化,添加相關2113屬性 # 。

# 表示對象已經初始化完成了。 Single._is_init = True你學會了嗎?學習更多編5261程的知識,不知道去哪裏找資料4102,黑馬程序員就有很多1653哦。

9. 單例模式怎樣寫

class StringManager {

private static StringManager instance;

private Map beanMap;

private StringManager() {

beanMap = new HashMap();

}

public static StringManager getInstance() {

if (instance == null) {

instance = new StringManager();

}

return instance;

}

public Object getBean(String beanName) {

return beanMap.get(beanName);

}

}

Tags:單例