欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

java代碼實(shí)現(xiàn)單例,java單例模式例子

java中的單例模式的代碼怎么寫

我從我的博客里把我的文章粘貼過來吧,對于單例模式模式應(yīng)該有比較清楚的解釋:

成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁設(shè)計(jì)、成都網(wǎng)站建設(shè)、微信開發(fā)、成都小程序開發(fā)、集團(tuán)成都企業(yè)網(wǎng)站定制等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:廣告設(shè)計(jì)等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶的一致贊賞!

單例模式在我們?nèi)粘5捻?xiàng)目中十分常見,當(dāng)我們在項(xiàng)目中需要一個(gè)這樣的一個(gè)對象,這個(gè)對象在內(nèi)存中只能有一個(gè)實(shí)例,這時(shí)我們就需要用到單例。

一般說來,單例模式通常有以下幾種:

1.饑漢式單例

public class Singleton {

private Singleton(){};

private static Singleton instance = new Singleton();

public static Singleton getInstance(){

return instance;

}

}

這是最簡單的單例,這種單例最常見,也很可靠!它有個(gè)唯一的缺點(diǎn)就是無法完成延遲加載——即當(dāng)系統(tǒng)還沒有用到此單例時(shí),單例就會(huì)被加載到內(nèi)存中。

在這里我們可以做個(gè)這樣的測試:

將上述代碼修改為:

public class Singleton {

private Singleton(){

System.out.println("createSingleton");

};

private static Singleton instance = new Singleton();

public static Singleton getInstance(){

return instance;

}

public static void testSingleton(){

System.out.println("CreateString");

}

}

而我們在另外一個(gè)測試類中對它進(jìn)行測試(本例所有測試都通過Junit進(jìn)行測試)

public class TestSingleton {

@Test

public void test(){

Singleton.testSingleton();

}

}

輸出結(jié)果:

createSingleton

CreateString

我們可以注意到,在這個(gè)單例中,即使我們沒有使用單例類,它還是被創(chuàng)建出來了,這當(dāng)然是我們所不愿意看到的,所以也就有了以下一種單例。

2.懶漢式單例

public class Singleton1 {

private Singleton1(){

System.out.println("createSingleton");

}

private static Singleton1 instance = null;

public static synchronized Singleton1 getInstance(){

return instance==null?new Singleton1():instance;

}

public static void testSingleton(){

System.out.println("CreateString");

}

}

上面的單例獲取實(shí)例時(shí),是需要加上同步的,如果不加上同步,在多線程的環(huán)境中,當(dāng)線程1完成新建單例操作,而在完成賦值操作之前,線程2就可能判

斷instance為空,此時(shí),線程2也將啟動(dòng)新建單例的操作,那么多個(gè)就出現(xiàn)了多個(gè)實(shí)例被新建,也就違反了我們使用單例模式的初衷了。

我們在這里也通過一個(gè)測試類,對它進(jìn)行測試,最后面輸出是

CreateString

可以看出,在未使用到單例類時(shí),單例類并不會(huì)加載到內(nèi)存中,只有我們需要使用到他的時(shí)候,才會(huì)進(jìn)行實(shí)例化。

這種單例解決了單例的延遲加載,但是由于引入了同步的關(guān)鍵字,因此在多線程的環(huán)境下,所需的消耗的時(shí)間要遠(yuǎn)遠(yuǎn)大于第一種單例。我們可以通過一段測試代碼來說明這個(gè)問題。

public class TestSingleton {

@Test

public void test(){

long beginTime1 = System.currentTimeMillis();

for(int i=0;i100000;i++){

Singleton.getInstance();

}

System.out.println("單例1花費(fèi)時(shí)間:"+(System.currentTimeMillis()-beginTime1));

long beginTime2 = System.currentTimeMillis();

for(int i=0;i100000;i++){

Singleton1.getInstance();

}

System.out.println("單例2花費(fèi)時(shí)間:"+(System.currentTimeMillis()-beginTime2));

}

}

最后輸出的是:

單例1花費(fèi)時(shí)間:0

單例2花費(fèi)時(shí)間:10

可以看到,使用第一種單例耗時(shí)0ms,第二種單例耗時(shí)10ms,性能上存在明顯的差異。為了使用延遲加載的功能,而導(dǎo)致單例的性能上存在明顯差異,

是不是會(huì)得不償失呢?是否可以找到一種更好的解決的辦法呢?既可以解決延遲加載,又不至于性能損耗過多,所以,也就有了第三種單例:

3.內(nèi)部類托管單例

public class Singleton2 {

private Singleton2(){}

private static class SingletonHolder{

private static Singleton2 instance=new Singleton2();

}

private static Singleton2 getInstance(){

return SingletonHolder.instance;

}

}

在這個(gè)單例中,我們通過靜態(tài)內(nèi)部類來托管單例,當(dāng)這個(gè)單例被加載時(shí),不會(huì)初始化單例類,只有當(dāng)getInstance方法被調(diào)用的時(shí)候,才會(huì)去加載

SingletonHolder,從而才會(huì)去初始化instance。并且,單例的加載是在內(nèi)部類的加載的時(shí)候完成的,所以天生對線程友好,而且也不需要

synchnoized關(guān)鍵字,可以說是兼具了以上的兩個(gè)優(yōu)點(diǎn)。

4.總結(jié)

一般來說,上述的單例已經(jīng)基本可以保證在一個(gè)系統(tǒng)中只會(huì)存在一個(gè)實(shí)例了,但是,仍然可能會(huì)有其他的情況,導(dǎo)致系統(tǒng)生成多個(gè)單例,請看以下情況:

public class Singleton3 implements Serializable{

private Singleton3(){}

private static class SingletonHolder{

private static Singleton3 instance = new Singleton3();

}

public static Singleton3 getInstance(){

return SingletonHolder.instance;

}

}

通過一段代碼來測試:

@Test

public void test() throws Exception{

Singleton3 s1 = null;

Singleton3 s2 = Singleton3.getInstance();

//1.將實(shí)例串行話到文件

FileOutputStream fos = new FileOutputStream("singleton.txt");

ObjectOutputStream oos =new ObjectOutputStream(fos);

oos.writeObject(s2);

oos.flush();

oos.close();

//2.從文件中讀取出單例

FileInputStream fis = new FileInputStream("singleton.txt");

ObjectInputStream ois = new ObjectInputStream(fis);

s1 = (Singleton3) ois.readObject();

if(s1==s2){

System.out.println("同一個(gè)實(shí)例");

}else{

System.out.println("不是同一個(gè)實(shí)例");

}

}

輸出:

不是同一個(gè)實(shí)例

可以看到當(dāng)我們把單例反序列化后,生成了多個(gè)不同的單例類,此時(shí),我們必須在原來的代碼中加入readResolve()函數(shù),來阻止它生成新的單例

public class Singleton3 implements Serializable{

private Singleton3(){}

private static class SingletonHolder{

private static Singleton3 instance = new Singleton3();

}

public static Singleton3 getInstance(){

return SingletonHolder.instance;

}

//阻止生成新的實(shí)例

public Object readResolve(){

return SingletonHolder.instance;

}

}

再次測試時(shí),就可以發(fā)現(xiàn)他們生成的是同一個(gè)實(shí)例了。

如何在Java中實(shí)現(xiàn)單例模式?

單例模式大致有五種寫法,分別為懶漢,惡漢,靜態(tài)內(nèi)部類,枚舉和雙重校驗(yàn)鎖。

1、懶漢寫法,常用寫法

class?LazySingleton{

private?static?LazySingleton?singleton;

private?LazySingleton(){

}

public?static?LazySingleton?getInstance(){

if(singleton==null){

singleton=new?LazySingleton();

}

return?singleton;

}???

}

2、惡漢寫法,缺點(diǎn)是沒有達(dá)到lazy loading的效果

class?HungrySingleton{

private?static?HungrySingleton?singleton=new?HungrySingleton();

private?HungrySingleton(){}

public?static?HungrySingleton?getInstance(){

return?singleton;

}

}

3、靜態(tài)內(nèi)部類,優(yōu)點(diǎn):加載時(shí)不會(huì)初始化靜態(tài)變量INSTANCE,因?yàn)闆]有主動(dòng)使用,達(dá)到Lazy loading

class?InternalSingleton{

private?static?class?SingletonHolder{

private?final?static??InternalSingleton?INSTANCE=new?InternalSingleton();

}???

private?InternalSingleton(){}

public?static?InternalSingleton?getInstance(){

return?SingletonHolder.INSTANCE;

}

}

4、枚舉,優(yōu)點(diǎn):不僅能避免多線程同步問題,而且還能防止反序列化重新創(chuàng)建新的對象

enum?EnumSingleton{

INSTANCE;

public?void?doSomeThing(){

}

}

5、雙重校驗(yàn)鎖,在當(dāng)前的內(nèi)存模型中無效

class?LockSingleton{

private?volatile?static?LockSingleton?singleton;

private?LockSingleton(){}

//詳見:

public?static?LockSingleton?getInstance(){

if(singleton==null){

synchronized(LockSingleton.class){

if(singleton==null){

singleton=new?LockSingleton();

}

}

}

return?singleton;

}

}

參考自:

如何在Java中使用雙重檢查鎖實(shí)現(xiàn)單例

你好!

一個(gè)常見情景,單例類在多線程環(huán)境中違反契約。如果你要一個(gè)新手寫出單例模式,可能會(huì)得到下面的代碼:

private static Singleton _instance;

public static Singleton getInstance() {

if (_instance == null) {

_instance = new Singleton();

}

return _instance;

}

然后,當(dāng)你指出這段代碼在超過一個(gè)線程并行被調(diào)用的時(shí)候會(huì)創(chuàng)建多個(gè)實(shí)例的問題時(shí),他很可能會(huì)把整個(gè)getInstance()方法設(shè)為同步(synchronized),就像我們展示的第二段示例代碼getInstanceTS()方法一樣。盡管這樣做到了線程安全,并且解決了多實(shí)例問題,但并不高效。在任何調(diào)用這個(gè)方法的時(shí)候,你都需要承受同步帶來的性能開銷,然而同步只在第一次調(diào)用的時(shí)候才被需要,也就是單例類實(shí)例創(chuàng)建的時(shí)候。這將促使我們使用雙重檢查鎖模式(double checked locking pattern),一種只在臨界區(qū)代碼加鎖的方法。程序員稱其為雙重檢查鎖,因?yàn)闀?huì)有兩次檢查 _instance == null,一次不加鎖,另一次在同步塊上加鎖。這就是使用Java雙重檢查鎖的示例:

public static Singleton getInstanceDC() {

if (_instance == null) { // Single Checked

synchronized (Singleton.class) {

if (_instance == null) { // Double checked

_instance = new Singleton();

}

}

}

return _instance;

}

這個(gè)方法表面上看起來很完美,你只需要付出一次同步塊的開銷,但它依然有問題。除非你聲明_instance變量時(shí)使用了volatile關(guān)鍵字。沒有volatile修飾符,可能出現(xiàn)Java中的另一個(gè)線程看到個(gè)初始化了一半的_instance的情況,但使用了volatile變量后,就能保證先行發(fā)生關(guān)系(happens-before relationship)。對于volatile變量_instance,所有的寫(write)都將先行發(fā)生于讀(read),在Java 5之前不是這樣,所以在這之前使用雙重檢查鎖有問題?,F(xiàn)在,有了先行發(fā)生的保障(happens-before guarantee),你可以安全地假設(shè)其會(huì)工作良好。另外,這不是創(chuàng)建線程安全的單例模式的最好方法,你可以使用枚舉實(shí)現(xiàn)單例模式,這種方法在實(shí)例創(chuàng)建時(shí)提供了內(nèi)置的線程安全。另一種方法是使用靜態(tài)持有者模式(static holder pattern)。

/*

* A journey to write double checked locking of Singleton class in Java.

*/

class Singleton {

private volatile static Singleton _instance;

private Singleton() {

// preventing Singleton object instantiation from outside

}

/*

* 1st version: creates multiple instance if two thread access

* this method simultaneously

*/

public static Singleton getInstance() {

if (_instance == null) {

_instance = new Singleton();

}

return _instance;

}

/*

* 2nd version : this definitely thread-safe and only

* creates one instance of Singleton on concurrent environment

* but unnecessarily expensive due to cost of synchronization

* at every call.

*/

public static synchronized Singleton getInstanceTS() {

if (_instance == null) {

_instance = new Singleton();

}

return _instance;

}

/*

* 3rd version : An implementation of double checked locking of Singleton.

* Intention is to minimize cost of synchronization and improve performance,

* by only locking critical section of code, the code which creates instance of Singleton class.

* By the way this is still broken, if we don't make _instance volatile, as another thread can

* see a half initialized instance of Singleton.

*/

public static Singleton getInstanceDC() {

if (_instance == null) {

synchronized (Singleton.class) {

if (_instance == null) {

_instance = new Singleton();

}

}

}

return _instance;

}

}

這就是本文的所有內(nèi)容了。這是個(gè)用Java創(chuàng)建線程安全單例模式的有爭議的方法,使用枚舉實(shí)現(xiàn)單例類更簡單有效。我并不建議你像這樣實(shí)現(xiàn)單例模式,因?yàn)橛肑ava有許多更好的方式。但是,這個(gè)問題有歷史意義,也教授了并發(fā)是如何引入一些微妙錯(cuò)誤的。正如之前所說,這是面試中非常重要的一點(diǎn)。

在去參加任何Java面試之前,要練習(xí)手寫雙重檢查鎖實(shí)現(xiàn)單例類。這將增強(qiáng)你發(fā)現(xiàn)Java程序員們所犯編碼錯(cuò)誤的洞察力。另外,在現(xiàn)在的測試驅(qū)動(dòng)開發(fā)中,單例模式由于難以被模擬其行為而被視為反模式(anti pattern),所以如果你是測試驅(qū)動(dòng)開發(fā)的開發(fā)者,最好避免使用單例模式。轉(zhuǎn)載,僅供參考。

如何實(shí)現(xiàn)單例模式?

這個(gè)模式保護(hù)類的創(chuàng)建過程來確保只有一個(gè)實(shí)例被創(chuàng)建,它通過設(shè)置類的構(gòu)造方法為私有來達(dá)到這個(gè)目的。 要獲得類的實(shí)例,單例類可以提供一個(gè)方法,如getInstance,來返回類的實(shí)例。該方法是唯一可以訪問類來創(chuàng)建實(shí)例的方法。 下面是單例的一個(gè)例子:Java代碼publicclassSingletonPattern{privatestaticSingletonPatterninstance;privateSingletonPattern(){}publicstatic synchronized SingletonPatterngetInstance(){if(instance==null){instance=newSingletonPattern();}returninstance;}} 當(dāng)我們要實(shí)現(xiàn)單例的時(shí)候,有如下的規(guī)則需要遵循: 從上面的示例代碼中可以看出,一個(gè)單例類有一個(gè)靜態(tài)的屬性來保存它唯一的實(shí)例 需要將類的構(gòu)造方法設(shè)置為private。這樣你不允許其他任何類來創(chuàng)建單例類的實(shí)例,因?yàn)樗鼈儾荒茉L問單例類的構(gòu)造方法。

如何用Java實(shí)現(xiàn)單例模式

單例模式:就是一個(gè)類僅創(chuàng)建一個(gè)對象;

public?class?Singleton?{

private?static?volatile?Singleton?singleton?=?null;

private?Singleton(){}//?構(gòu)造方法

public?static?Singleton?getSingleton(){//?單例模式

if(singleton?==?null){

synchronized?(Singleton.class){

if(singleton?==?null){

singleton?=?new?Singleton();

}

}

}

return?singleton;

}????

}

JAVA單例模式的幾種實(shí)現(xiàn)方法

JAVA

單例模式的幾種實(shí)現(xiàn)方法

1.餓漢式單例類

package

pattern.singleton;

//

餓漢式單例類

.

在類初始化時(shí),已經(jīng)自行實(shí)例化

public

class

Singleton1

{

//

私有的默認(rèn)構(gòu)造子

private

Singleton1()

{}

//

已經(jīng)自行實(shí)例化

private

static

final

Singleton1

single

=

new

Singleton1();

//

靜態(tài)工廠方法

public

static

Singleton1

getInstance()

{

return

single;

}

}

2.

懶漢式單例類

package

pattern.singleton;

//

懶漢式單例類

.

在第一次調(diào)用的時(shí)候?qū)嵗?/p>

public

class

Singleton2

{

//

私有的默認(rèn)構(gòu)造子

private

Singleton2()

{}

//

注意,這里沒有

final

private

static

Singleton2

single;

//

只實(shí)例化一次

static

{

single

=

new

Singleton2();

}

//

靜態(tài)工廠方法

public

synchronized

static

Singleton2

getInstance()

{

if

(single

==

null

)

{

single

=

new

Singleton2();

}

return

single;

}

}

在上面給出懶漢式單例類實(shí)現(xiàn)里對靜態(tài)工廠方法使用了同步化,以處理多線程環(huán)境。有些設(shè)計(jì)師在這里建議使用所謂的

"

雙重檢查成例

".

必須指出的是,

"

雙重檢查成例

"

不可以在

Java

語言中使用。不十分熟悉的讀者,可以看看后面給出的小節(jié)。

樣,由于構(gòu)造子是私有的,因此,此類不能被繼承。餓漢式單例類在自己被加載時(shí)就將自己實(shí)例化。即便加載器是靜態(tài)的,在餓漢

式單例類被加載時(shí)仍會(huì)將自己實(shí)例化。單從資源利用效率角度來講,這個(gè)比懶漢式單例類稍差些。從速度和反應(yīng)時(shí)間角度來講,

比懶漢式單例類稍好些。然而,懶漢式單例類在實(shí)例化時(shí),必須處

理好在多個(gè)線程同時(shí)首次引用此類時(shí)的訪問限制問題,特別是當(dāng)單例類作為資源控制器,在實(shí)例化時(shí)必然涉及資源初始化,而資源

初始化很有可能耗費(fèi)時(shí)間。這意味著出現(xiàn)多線程同時(shí)首次引用此類的機(jī)率變得較大。

餓漢式單例類可以在

Java

語言內(nèi)實(shí)現(xiàn),

但不易在

C++

內(nèi)實(shí)現(xiàn),因?yàn)殪o態(tài)初始化在

C++

里沒有固定的順序,因而靜態(tài)的

m_instance

變量的初始化與類的加載順序沒有保證,可能會(huì)出問題。這就是為什么

GoF

在提出單例類的概念時(shí),舉的例子是懶

漢式的。他們的書影響之大,以致

Java

語言中單例類的例子也大多是懶漢式的。實(shí)際上,本書認(rèn)為餓漢式單例類更符合

Java

言本身的特點(diǎn)。

3.

登記式單例類

.

package

pattern.singleton;

import

java.util.HashMap;

import

java.util.Map;

//

登記式單例類

.

//

類似

Spring

里面的方法,將類名注冊,下次從里面直接獲取。

public

class

Singleton3

{

private

static

MapString,Singleton3

map

=

new

HashMapString,Singleton3();

static

{

Singleton3

single

=

new

Singleton3();

map.put(single.getClass().getName(),

single);

}

//

保護(hù)的默認(rèn)構(gòu)造子

protected

Singleton3(){}

//

靜態(tài)工廠方法

,

返還此類惟一的實(shí)例

public

static

Singleton3

getInstance(String

name)

{

if

(name

==

null

)

{

name

=

Singleton3.

class

.getName();

System.out.println("name

==

null"+"---name="+name);

}

if

(map.get(name)

==

null

)

{

try

{

map.put(name,

(Singleton3)

Class.forName(name).newInstance());

}

catch

(InstantiationException

e)

{

e.printStackTrace();

}

catch

(IllegalAccessException

e)

{

e.printStackTrace();

}

catch

(ClassNotFoundException

e)

{

e.printStackTrace();

}

}

return

map.get(name);

}

//

一個(gè)示意性的商業(yè)方法

public

String

about()

{

return

"Hello,

I

am

RegSingleton.";

}

public

static

void

main(String[]

args)

{

Singleton3

single3

=

Singleton3.getInstance(

null

);

System.out.println(single3.about());

}

}

本文名稱:java代碼實(shí)現(xiàn)單例,java單例模式例子
瀏覽路徑:http://chinadenli.net/article42/hddiec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、建站公司、網(wǎng)站收錄、App設(shè)計(jì)網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司