Java 多线程(四)—— 单例模式
這篇博客介紹線程安全的應(yīng)用——單例模式。
單例模式
? 單例模式,是一種常用的軟件設(shè)計(jì)模式。在它的核心結(jié)構(gòu)中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統(tǒng)中,應(yīng)用該模式的類一個類只有一個實(shí)例。即一個類只有一個對象實(shí)例。
雙重校驗(yàn)鎖
實(shí)例:
/*** @author: ChenHao* 關(guān)于懶漢式的線程安全問題,使用同步機(jī)制* 對于一般的方法內(nèi),使用同步方法塊,可以考慮使用this* 對于靜態(tài)方法而言,使用當(dāng)前類充當(dāng)鎖。*/ public class TestSingleton {public static void main(String[] args) {System.out.println(MySingle.getInstance());System.out.println(MySingle.getInstance());} }class MySingle{//聲明一個私有的靜態(tài)變量,第一次調(diào)用才初始化,避免內(nèi)存浪費(fèi)。private volatile static MySingle instance=null;//讓構(gòu)造器為private私有化,避免外部直接創(chuàng)建對象private MySingle(){}public static MySingle getInstance(){if(null ==instance){//提高效率:如果已經(jīng)存在對象,則不進(jìn)行鎖等待,直接返回對象,只有當(dāng)對象為空才會進(jìn)入鎖等待,這里可以在第一個進(jìn)入鎖創(chuàng)建對象后,sleep10秒來放大效果//這里有五個線程等待synchronized(MySingle.class){//第一次:當(dāng)一個線程進(jìn)來后,其他線程都在鎖外面//第一個線程創(chuàng)建對象后,釋放鎖,其他線程得到鎖后,如果instance不為null,則不需要創(chuàng)建if(null ==instance){instance =new MySingle();try {Thread.currentThread().sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}return instance;} }代碼分析:多個線程同時創(chuàng)建MySingle類的實(shí)例,比如現(xiàn)在有6個線程,第一次同時調(diào)用getInstance()靜態(tài)方法,
線程A獲取了鎖,其他5個線程都在synchronized(MySingle.class)外面等待,第一個線程創(chuàng)建對象后,釋放鎖,其他線程得到鎖后,如果instance不為null,則不需要創(chuàng)建;
第一個if(null ==instance)作用是提高效率:如果已經(jīng)存在對象,則不進(jìn)行鎖等待,直接返回對象,只有當(dāng)對象為空才會進(jìn)入鎖等待,這里可以在第一個進(jìn)入鎖創(chuàng)建對象后,sleep10秒來放大效果,此時已經(jīng)創(chuàng)建了instance ,但是還沒有釋放鎖,所以新來的線程不需要再等待鎖,直接使用已經(jīng)創(chuàng)建好的instance;
第二個if(null ==instance)判斷instance是否已經(jīng)存在,如果第一個線程已經(jīng)創(chuàng)建instance,并釋放鎖,接下來的線程進(jìn)入后則不需要再創(chuàng)建;
運(yùn)行結(jié)果:輸出相同的對象實(shí)例
餓漢
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }CAS(AtomicReference)實(shí)現(xiàn)單例模式
public class Singleton {private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>(); private Singleton() {}public static Singleton getInstance() {for (;;) {Singleton singleton = INSTANCE.get();if (null != singleton) {return singleton;}singleton = new Singleton();if (INSTANCE.compareAndSet(null, singleton)) {return singleton;}}} }用CAS的好處在于不需要使用傳統(tǒng)的鎖機(jī)制來保證線程安全,CAS是一種基于忙等待的算法,依賴底層硬件的實(shí)現(xiàn),相對于鎖它沒有線程切換和阻塞的額外消耗,可以支持較大的并行度。
CAS的一個重要缺點(diǎn)在于如果忙等待一直執(zhí)行不成功(一直在死循環(huán)中),會對CPU造成較大的執(zhí)行開銷。而且,這種寫法如果有多個線程同時執(zhí)行singleton = new Singleton();也會比較浪費(fèi)堆內(nèi)存。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/java-chen-hao/p/9896966.html
總結(jié)
以上是生活随笔為你收集整理的Java 多线程(四)—— 单例模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java解析html的table
- 下一篇: Apache发布TomEE 7.1,支持