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