1. 程式人生 > >經典設計模式(二):單例模式

經典設計模式(二):單例模式

版權宣告

最近很多爬蟲來我部落格爬文章,轉載可以,但請保留原文出處及版權宣告,即便是在中國

單純的廣告

個人部落格:https://aodeng.cc
微信公眾號:低調小熊貓
QQ群:756796932

簡介

單例模式確保一個類只有一個例項,並提供一個全域性訪問點,上班偷偷寫的文章,所以請仔細看註釋

使用

懶漢式

/**
 * @program:hope
 * @author:aodeng
 * @blog:低調小熊貓(https://aodeng.cc)
 * @微信公眾號:低調小熊貓
 * @create:2018-11-15 13:20
 **/
public class SingleObject {
    /**===============懶漢式(那個取的名字,本人表示根本記不住)英文名,叫 lazy loading,也就是延遲載入===============**/
    private static SingleObject instance;
    /**讓建構函式為 private,這樣該類就不會被例項化**/
    private SingleObject(){}
    /**但是上面程式碼會有一個問題,當多個執行緒同時呼叫 getInstance() 方法時,可能會產生多個instance 例項,因此這種方式並不是真正的單例。
       為了解決執行緒安全問題,我們只需要在getInstance() 方法上使用synchronized 關鍵字給執行緒加鎖即可
       synchronized 的作用是加鎖,當多個執行緒同時呼叫getInstance() 時,只有一個執行緒能進入,其他執行緒會等待進入的執行緒出來之後在一一進入,
       這樣就能保證instance 例項是唯一的。這才是真正的單例,不過這並不是完美的解決方案,只要是鎖,必然有效能損耗問題。而且對於上面的程式碼,
       其實我們只需要線上程第一次訪問時加鎖即可,之後並不需要鎖,鎖給我們帶來了系統資源浪費**/
    public static synchronized SingleObject getInstance(){
        if (null == instance){
            instance=new SingleObject();
        }
        return instance;
    }

    private String name="低調小熊貓";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

餓漢式

/**
 * @program:hope
 * @author:aodeng
 * @blog:低調小熊貓(https://aodeng.cc)
 * @微信公眾號:低調小熊貓
 * @create:2018-11-15 13:34
 **/
public class SingleObject2 {
    /**=======餓漢式(低調小熊貓表示還是記不住)新的解決方案是not lazy loading,在類載入時就建立好了例項,解決懶漢式鎖給我們帶來了系統資源浪費===============**/
    private static SingleObject2 instance=new SingleObject2();
    private SingleObject2(){}
    public static SingleObject2 getInstance(){
        return instance;
    }
    /**這種方式就可以保證例項唯一了**/
    private String name="低調小熊貓2";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

double-checked locking (雙重檢查加鎖)

/**
 * @program:hope
 * @author:aodeng
 * @blog:低調小熊貓(https://aodeng.cc)
 * @微信公眾號:低調小熊貓
 * @create:2018-11-15 13:45
 **/
public class SingleObject3 {
    /**=======還有一種叫 double-checked locking (雙重檢查加鎖)==============**/
    /**這種方式主要用到兩個關鍵字volatile 和 synchronized,synchronized 的作用是加鎖,就不再多說,而volatile 關鍵字許多人不瞭解,沒關係,我們先看程式碼**/
    private volatile static SingleObject3 instance;
    private SingleObject3(){}
    private static SingleObject3 getInstance(){
        if (null == instance) {
            synchronized (SingleObject3.class){
                if (null == instance){
                    instance =new SingleObject3();
                }
            }
        }
        return instance;
    }
    /**volatile 關鍵字簡單來說就是可以保證instance變數在被其中一個執行緒new出來時,其他執行緒可以立即看到結果並正確的處理它。對volatile 有興趣的朋友可以自行度娘
     * 這種方式的單例模式可以大大的減少鎖所帶來的效能損耗**/
    private String name="低調小熊貓3";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

TestMain

/**
 * @program:hope
 * @author:aodeng
 * @blog:低調小熊貓(https://aodeng.cc)
 * @微信公眾號:低調小熊貓
 * @create:2018-11-15 13:23
 **/
public class TestMain {
    public static void main(String[] args) {
        /**======單例使用========**/
        //懶漢式
        SingleObject singleObject=SingleObject.getInstance();
        //餓漢式
        SingleObject2 singleObject2=SingleObject2.getInstance();
        //雙重檢查加鎖,額,是不是很尷尬,我不知道怎麼用這個
        //SingleObject3 singleObject3=SingleObject3.
        System.out.println(singleObject.getName());
        System.out.println(singleObject2.getName());
        /**
         * 優點
         使用單例模式,物件在記憶體中只有一個例項,並且無需頻繁的建立和銷燬物件,大大的減少了效能的損耗
         缺點:懶得打字了,可以忽略
         個人喜歡使用餓漢式單例,也就是not lazy loading,沒有為什麼,就是這種程式碼少點,嘿嘿
         **/
    }
}

原始碼連結

https://github.com/java-aodeng/hope