單列模式與多執行緒

2022-07-22 13:39:20 字數 3981 閱讀 3858

在23個標準設計模式中,單例模式在應用中還是很常見的,但是在多執行緒環境中,單例模式的使用有非常多的坑,使用好單例模式的乙個原則:如何使單例模式在遇到多執行緒的環境中是安全的、正確的。下面分析幾種多執行緒的實現方式以及遇到的坑。

立即載入:實用類的時候已經將物件建立完畢,常見的是直接new例項化,有「著急」,「急迫」的意思,因此也稱:「餓漢模式」。在呼叫方法前,已經例項化物件。**如下:

單例模式:

public

class

singleton01

public

static

singleton01 getinstance()

}

執行緒:

public

class mythread extends

thread

}

測試類:

public

class

run

}

執行結果:

所有執行緒的物件hashcode均是一樣的,證明是單例模式,but,該**的實現是優缺點的:不能有其他例項變數,因為getinstance方法沒有同步,可能會出現執行緒安全問題。

延遲載入:在呼叫方法的時候,物件才被例項化,常用的實現方式就是在方法內部例項化物件。**如下:

單例模式:

public

class

singleton02

public

static

singleton02 getinstance()

return

instance;}}

執行緒類:

public

class mythread extends

thread

}

測試類:

public

class

run

}

執行結果:

從執行結果來看,控制台列印了多個hashcode值,說明該實現方式在多執行緒的環境中是失敗的,如何解決呢?其實很簡單,讓方法同步即可,使用synchronized關鍵字。改進後**吐下:

public

class

singleton02

synchronized

public

static

singleton02 getinstance()

} catch

(interruptedexception e)

return

instance;}}

再次執行:

同步之後,證明該單例模式是正確的。但是,這種方式又帶來一種缺點,那就是效率問題,因為下乙個執行緒必須需要等上乙個執行緒釋放鎖之後才能執行,需要排隊執行,因此還可以優化,那就是:嘗試同步**塊,針對重要**進行單獨同步,以提公升效率。

下面總結了一種使用dcl雙檢查鎖機制實現單例模式,該模式適用於在多執行緒環境中的延遲載入單例模式設計。**如下:

public

class

singleton03

public

static

singleton03 getinstance()}}

} catch

(interruptedexception e)

return

instance;}}

這種方式既保證了執行緒的安全性,還保證了效率。

前面的改進方式可以實現在多執行緒的環境中實現單例模式,並且保證執行緒安全,那麼這種靜態內建類的方式也可以實現同樣的效果。建立靜態內類,如下:

public

class

singleton04

public

singleton04()

public

static

singleton04 getinstance()

}

執行緒類:

public

class mythread extends

thread

}

測試類同上

執行結果:

靜態內建類固然可以實現單例模式,但是這裡有乙個坑,那就是在遇到序列化和反序列化的時候,依然會出現問題,依然會出現多個例項化物件,**如下:

單例模式

public

class singleton05 implements

serializable

public

singleton05()

public

static

singleton05 getinstance()

}

序列化執行類:

public

class

run2

catch

(ioexception e)

//讀try

catch (ioexception |classnotfoundexception e)

}

執行結果:

很明顯,寫入和讀出來的物件不是乙個,顯然不符合單例模式的設計模式。序列化破壞了單例模式,當然,還有一種破壞單例模式的方式,那就是反射,單例模式中盡量不要使用反射。呢麼問題來了,如何改進呢,其實很簡單,在序列化的時候在呼叫乙個方法。改進如下:

public

class singleton05 implements

serializable

public

singleton05()

public

static

singleton05 getinstance()

protected object readresolve()throws

objectstreamexception

}

再次執行:

序列化操作提供了乙個很特別的鉤子(hook)-類中具有乙個私有的被例項化的方法readresolve(),這個方法可以確保類的開發人員在序列化將會返回怎樣的object上具有發言權。這樣就確保我們在反序列化的時候返回的物件是同乙個。

靜態**塊中的**執行實在實用類的時候載入,因此我們可以應用靜態**塊的這種特性來設計單例模式。**如下:

public

class

singleton06

static

public

static

singleton06 getinstance()

}

執行緒類測試類同三,結果如下:

}測試執行類同上,結果如下:

特點就是實現非常簡單。

多執行緒(4)單列模式

單列模式分為兩種 餓漢式 package util public class single public static single getsingle 懶漢式 package util public class single public static single getsingle retur...

終於理解單列模式了,單列模式和多執行緒

1 單例類確保自己只有乙個例項 構造方法私有化 2 單例類必須自己建立自己的例項。3 單例類必須為其他物件提供唯一的例項。package singleton 懶漢式 單例例項在第一次被使用時構建,延遲初始化。public class singleton return sing public void...

c 單列模式與執行緒安全

通常c 裡面的單列模式很容易實現,我們也不需要去考慮其執行緒安全的問題,但是在多執行緒環境中我們卻必須要考慮到。首先我們來分析下一下的這個單列模式為什麼不是執行緒安全的,通常的單列模式寫法 class msgofarrival msgofarrival msgofarrival m pinstanc...