java單例設計模式

單例設計模式就是要保證單個類的對象在內存中的唯一性。外部不能new單例設計的 類對象,所以必須私有其構造方法。

  1. 保證唯一性,構造方法只能私有
  2. 構造私有,外部無法建立對象,所以只能內部new對象
  3. 為了拿到對象,接著只能建立靜態(tài)方法(外部沒有辦法new對象,所以只能類名調用靜態(tài)方法),返回內部對象
  4. 又因為靜態(tài)不能訪問非靜態(tài),所以內部對象也只能是靜態(tài)的

單例設計模式也叫餓漢,除此之外還有一種叫懶漢(內部對象的延遲加載,線程不安全),詳情見代碼

demo:

package single;
/*
 * 單利設計模式,保證對象在內存中的唯一性
 * 
 * 1.保證唯一性,構造方法只能私有
 * 2.構造私有,外部無法建立對象
 * 3.只能內部new對象出來
 * 4.為了拿到對象,接著只能建立靜態(tài)方法,返回內部對象
 * 5.靜態(tài)不能訪問非靜態(tài),所以內部對象也只能是靜態(tài)的
 * 
 * 懶漢式線程不安全
 * 
 * java內的Runtime也是單例設計模式
 */
public class SingleTest {
    public static void main(String[] args) {
        
        /*
         * 單例(餓漢式)
         */
        //外部無論如何獲取,都只能拿到一個對象
        Single s = Single.getInstance();
        System.out.println(s);
        
        Single s1 = Single.getInstance();
        System.out.println(s1);
        
        /*
         * 單例(懶漢式)
         */
        SingleL sL = SingleL.getInstance();
        System.out.println(sL);
        
        SingleL sL1 = SingleL.getInstance();
        System.out.println(sL1);
    }
}

//單例類(餓漢式)
class Single{
    private static Single s = new Single();
    
    private Single(){}
    
    public static Single getInstance(){
        return s;
    }
}
//單例類(懶漢式) 延遲加載 ,線程不安全
class SingleL{
    private static  SingleL s = null;
    
    private SingleL(){}
    
    public static SingleL getInstance(){
        if(s == null)
            s = new SingleL();
        return s;
    }
}

java內也有單例設計模式的類對象:Runtime類,源碼如下(JAVA 1.8)

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /** Don't let anyone else instantiate this class */
    private Runtime() {}
  ...
}

上文提到了懶漢模式(延遲加載)是有線程安全問題的。下面就解釋為什么在多線程下會出現(xiàn)不安全的情況,怎么來解決這個問題。

原因:
出現(xiàn)不安全的因素其實很簡單,因為多線程下會并發(fā)的訪問getInstance方法,有可能一個進程執(zhí)行到if(s == null)這個邏輯代碼塊中,此時線程跳走了,但是對象還沒new出來。,另一個進程又加載運行了此方法。接著原來的那個進程執(zhí)行完剩下的代碼。這樣就new了兩次對象,導致出現(xiàn)了多個單例對象的實例,產(chǎn)生了不安全的因素。

那如何來解決呢,具體方法請看下面的示例代碼。
code:

package thread;

/*
 * 懶漢的多線程安全問題解決
 */
public class ThreadDemo3 {
    public static void main(String[] args) {

        // 建立多線程,來運行
        SingleThread s = new SingleThread();

        /*
         * 結果出現(xiàn)了兩個懶漢的實例
         *
         * thread.Single2@6b2ce86d 
         * thread.Single2@719e4b38
         * 
         * 解決辦法: 將getInstace的方法變?yōu)橥椒椒ǎ蛘呒油酱a塊
         */
        new Thread(s).start();
        new Thread(s).start();

    }
}

// 來一個懶漢類
class Single2 {
    private static Single2 s = null;

    private Single2() {
    }

    public static Single2 getInstance() {
        // 靜態(tài)方法,鎖上class
        // 雙重if,避免不必要的進入同步代碼塊,提高效率
        if (s == null) {
            synchronized (Single2.class) {
                if (s == null)
                    s = new Single2();
            }
        }
        return s;
    }
}

// 來一個Runnable的子類來玩懶漢
class SingleThread implements Runnable {
    public void run() {
        for (int i = 0; i < 20; i++) {
            Single2 s2 = Single2.getInstance();
            System.out.println(s2);
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.應用場景: 當需要保證類在內存中的對象唯一性,可以使用單例模式,不想創(chuàng)建多個實例浪費資源,或者避免多個實例由于...
    發(fā)光的魚閱讀 269評論 0 0
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • Java中單例(Singleton)模式是一種廣泛使用的設計模式。單例模式的主要作用是保證在Java程序中,某個類...
    徘徊0_閱讀 317評論 0 0
  • 單例模式(SingletonPattern)一般被認為是最簡單、最易理解的設計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,292評論 4 34
  • 時間飛逝,就這樣過了31天。想想這31天,自己每天到底做了些什么? 一踏糊涂啊,每天看似很忙碌,看似很棄...
    靈魂獸者閱讀 148評論 4 5