日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java单例设计模式_Java设计模式之单例模式详解

發(fā)布時(shí)間:2023/12/10 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java单例设计模式_Java设计模式之单例模式详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在Java開(kāi)發(fā)過(guò)程中,很多場(chǎng)景下都會(huì)碰到或要用到單例模式,在設(shè)計(jì)模式里也是經(jīng)常作為指導(dǎo)學(xué)習(xí)的熱門(mén)模式之一,相信每位開(kāi)發(fā)同事都用到過(guò)。我們總是沿著前輩的足跡去做設(shè)定好的思路,往往沒(méi)去探究為何這么做,所以這篇文章對(duì)單例模式做了詳解。

一、單例模式定義:

單例模式確保某個(gè)類(lèi)只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。在計(jì)算機(jī)系統(tǒng)中,線程池、緩存、日志對(duì)象、對(duì)話框、打印機(jī)、顯卡的驅(qū)動(dòng)程序?qū)ο蟪1辉O(shè)計(jì)成單例。這些應(yīng)用都或多或少具有資源管理器的功能。每臺(tái)計(jì)算機(jī)可以有若干個(gè)打印機(jī),但只能有一個(gè)Printer Spooler,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)中。每臺(tái)計(jì)算機(jī)可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個(gè)通信端口同時(shí)被兩個(gè)請(qǐng)求同時(shí)調(diào)用。總之,選擇單例模式就是為了避免不一致?tīng)顟B(tài),避免政出多頭。

二、單例模式特點(diǎn):

1、單例類(lèi)只能有一個(gè)實(shí)例。

2、單例類(lèi)必須自己創(chuàng)建自己的唯一實(shí)例。

3、單例類(lèi)必須給所有其他對(duì)象提供這一實(shí)例。

單例模式保證了全局對(duì)象的唯一性,比如系統(tǒng)啟動(dòng)讀取配置文件就需要單例保證配置的一致性。

三、線程安全的問(wèn)題

一方面在獲取單例的時(shí)候,要保證不能產(chǎn)生多個(gè)實(shí)例對(duì)象,后面會(huì)詳細(xì)講到五種實(shí)現(xiàn)方式;

另一方面,在使用單例對(duì)象的時(shí)候,要注意單例對(duì)象內(nèi)的實(shí)例變量是會(huì)被多線程共享的,推薦使用無(wú)狀態(tài)的對(duì)象,不會(huì)因?yàn)槎鄠€(gè)線程的交替調(diào)度而破壞自身狀態(tài)導(dǎo)致線程安全問(wèn)題,比如我們常用的VO,DTO等(局部變量是在用戶棧中的,而且用戶棧本身就是線程私有的內(nèi)存區(qū)域,所以不存在線程安全問(wèn)題)。

四、單例模式的選擇

還記得我們最早使用的MVC框架Struts1中的action就是單例模式的,而到了Struts2就使用了多例。在Struts1里,當(dāng)有多個(gè)請(qǐng)求訪問(wèn),每個(gè)都會(huì)分配一個(gè)新線程,在這些線程,操作的都是同一個(gè)action對(duì)象,每個(gè)用戶的數(shù)據(jù)都是不同的,而action卻只有一個(gè)。到了Struts2,?action對(duì)象為每一個(gè)請(qǐng)求產(chǎn)生一個(gè)實(shí)例,并不會(huì)帶來(lái)線程安全問(wèn)題(實(shí)際上servlet容器給每個(gè)請(qǐng)求產(chǎn)生許多可丟棄的對(duì)象,但是并沒(méi)有影響到性能和垃圾回收問(wèn)題,有時(shí)間會(huì)做下研究)。

五、實(shí)現(xiàn)單例模式的方式

1.餓漢式單例(立即加載方式)

//餓漢式單例

public classSingleton1 {//私有構(gòu)造

privateSingleton1() {}private static Singleton1 single = newSingleton1();//靜態(tài)工廠方法

public staticSingleton1 getInstance() {returnsingle;

}

}

餓漢式單例在類(lèi)加載初始化時(shí)就創(chuàng)建好一個(gè)靜態(tài)的對(duì)象供外部使用,除非系統(tǒng)重啟,這個(gè)對(duì)象不會(huì)改變,所以本身就是線程安全的。

Singleton通過(guò)將構(gòu)造方法限定為private避免了類(lèi)在外部被實(shí)例化,在同一個(gè)虛擬機(jī)范圍內(nèi),Singleton的唯一實(shí)例只能通過(guò)getInstance()方法訪問(wèn)。(事實(shí)上,通過(guò)Java反射機(jī)制是能夠?qū)嵗瘶?gòu)造方法為private的類(lèi)的,那基本上會(huì)使所有的Java單例實(shí)現(xiàn)失效。此問(wèn)題在此處不做討論,姑且閉著眼就認(rèn)為反射機(jī)制不存在。)

2.懶漢式單例(延遲加載方式)

//懶漢式單例

public classSingleton2 {//私有構(gòu)造

privateSingleton2() {}private static Singleton2 single = null;public staticSingleton2 getInstance() {if(single == null){

single= newSingleton2();

}returnsingle;

}

}

該示例雖然用延遲加載方式實(shí)現(xiàn)了懶漢式單例,但在多線程環(huán)境下會(huì)產(chǎn)生多個(gè)single對(duì)象,如何改造請(qǐng)看以下方式:

使用synchronized同步鎖

public classSingleton3 {//私有構(gòu)造

privateSingleton3() {}private static Singleton3 single = null;public staticSingleton3 getInstance() {//等同于 synchronized public static Singleton3 getInstance()

synchronized(Singleton3.class){//注意:里面的判斷是一定要加的,否則出現(xiàn)線程安全問(wèn)題

if(single == null){

single= newSingleton3();

}

}returnsingle;

}

}

在方法上加synchronized同步鎖或是用同步代碼塊對(duì)類(lèi)加同步鎖,此種方式雖然解決了多個(gè)實(shí)例對(duì)象問(wèn)題,但是該方式運(yùn)行效率卻很低下,下一個(gè)線程想要獲取對(duì)象,就必須等待上一個(gè)線程釋放鎖之后,才可以繼續(xù)運(yùn)行。

public classSingleton4 {//私有構(gòu)造

privateSingleton4() {}private static Singleton4 single = null;//雙重檢查

public staticSingleton4 getInstance() {if (single == null) {synchronized (Singleton4.class) {if (single == null) {

single= newSingleton4();

}

}

}returnsingle;

}

}

使用雙重檢查進(jìn)一步做了優(yōu)化,可以避免整個(gè)方法被鎖,只對(duì)需要鎖的代碼部分加鎖,可以提高執(zhí)行效率。

3.靜態(tài)內(nèi)部類(lèi)實(shí)現(xiàn)

public classSingleton6 {//私有構(gòu)造

privateSingleton6() {}//靜態(tài)內(nèi)部類(lèi)

private static classInnerObject{private static Singleton6 single = newSingleton6();

}public staticSingleton6 getInstance() {returnInnerObject.single;

}

}

靜態(tài)內(nèi)部類(lèi)雖然保證了單例在多線程并發(fā)下的線程安全性,但是在遇到序列化對(duì)象時(shí),默認(rèn)的方式運(yùn)行得到的結(jié)果就是多例的。這種情況不多做說(shuō)明了,使用時(shí)請(qǐng)注意。

4.static靜態(tài)代碼塊實(shí)現(xiàn)

public classSingleton6 {//私有構(gòu)造

privateSingleton6() {}private static Singleton6 single = null;//靜態(tài)代碼塊

static{

single= newSingleton6();

}public staticSingleton6 getInstance() {returnsingle;

}

}

5.內(nèi)部枚舉類(lèi)實(shí)現(xiàn)

public classSingletonFactory {//內(nèi)部枚舉類(lèi)

private enumEnmuSingleton{

Singleton;privateSingleton8 singleton;//枚舉類(lèi)的構(gòu)造方法在類(lèi)加載是被實(shí)例化

privateEnmuSingleton(){

singleton= newSingleton8();

}publicSingleton8 getInstance(){returnsingleton;

}

}public staticSingleton8 getInstance() {returnEnmuSingleton.Singleton.getInstance();

}

}classSingleton8{publicSingleton8(){}

}

以上就是本文要介紹的所有單例模式的理解和實(shí)現(xiàn),相信這篇文章能讓大家更清楚的理解單例模式,希望大家有問(wèn)題可以探討,多多指教!

備注:本文單例實(shí)現(xiàn)部分,實(shí)例源碼參照《Java多線程編程核心技術(shù)》-(高洪巖)一書(shū)中第六章的學(xué)習(xí)案例撰寫(xiě)。

總結(jié)

以上是生活随笔為你收集整理的java单例设计模式_Java设计模式之单例模式详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。