Java單例模式--懶漢式和餓漢式(Demo)

你好我是辰兮,很高興你能來閱讀,本篇文章爲大家講解Java單例模式,相關的更多面試知識已經提前整理好文章可以閱讀學習,分享獲取新知,希望對Java初學者有幫助。



一、序言

單件模式屬於工廠模式的特例,只是它不需要輸入參數並且始終返回同一對象的引用。

  • 1、單例類只能有一個實例
  • 2、單例類必須自己創建自己的唯一實例。
  • 3、單例類必須給所有其他對象提供這一實例。

二、餓漢式

餓漢式:在程序啓動或單例模式類被加載的時候,單例模式實例就已經被創建。

參考例子如下

  • 我們用HashSet來存儲對象,因爲HashSet只能存放不同的元素,如果輸出的對象唯一,則代表是單例模式。參考class King
  • HashSet類,是存在於java.util包中的類 。同時也被稱爲集合,該容器中只能存儲不重複的對象。
import java.util.HashSet;

public class TheadDemo {

    static HashSet<King> hs = new HashSet<>();
    static Runnable r = new Runnable() {
        @Override
        public void run() {
            //獲取單例對象
            King king = King.currentInstance();
            //將獲取到的單例對象添加到集合中
            hs.add(king);
        }
    };
    public static void main(String[] args) {
        //需求:多條線程同時去獲取單例對象,然後將獲取到的單例對象添加到HashSet中
        // 創建多個線程對象,同時訪問 單例對象
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(r);
            thread.start();           
        }
        System.out.println(hs);
    }
}
//餓漢式
class King {
    private static King instance = new King();
    private King(){}
    public static King currentInstance() {
        return instance;
    }
} 
[King@2cf062b0]

小結:如King類,先創建一個類,直接在內中初始化,再創建一個方法調用這個類返回值是該類的對象。


三、懶漢式

懶漢式:當程序第一次訪問單例模式實例時才進行創建。
參考class Queue

ps:懶漢式本身是非線程安全的 --爲了實現線程安全加了synchronized

import java.util.HashSet;

public class TheadDemo {

    static HashSet<Queue> hs = new HashSet<>();
    static Runnable r = new Runnable() {
        @Override
        public void run() {
            //獲取單例對象
            Queue queue = Queue.currentInstance();
            //將獲取到的單Queue對象添加到集合中
            hs.add(queue);
        }
    };
    public static void main(String[] args) {
        //需求:多條線程同時去獲取單例對象,然後將獲取到的單例對象添加到HashSet中
        // 創建多個線程對象,同時訪問 單例對象
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(r);
            thread.start();
        }
        System.out.println(hs);
    }

}

//懶漢式
class Queue {
    private static Queue instance;
    private Queue() { }
    //使用同步代碼塊,同步方法,以及同步鎖都可以解決
    public synchronized static Queue currentInstance() {
        if (instance == null) {
            instance = new Queue();
        }
        return instance;
    }
}
[Queue@3cbeafaf]

小結:如Queue類,先創建一個對象沒有給他賦值,默認爲null,如果調用的話我就自己創建一個對象,再次調用的話就返回原來創建的對象。


四、拓展小結

你一定很好奇爲什麼叫餓漢式和懶漢式,我們如何記憶呢?

餓漢式:直接new對象,再創建方法調用

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

不管程序是否需要這個對象的實例,總是在類加載的時候就先創建好實例,理解起來就像不管一個人想不想吃東西都把吃的先買好,如同餓怕了一樣。


懶漢式:如果需要在創建,如果已經創建則返回原來創建的。

public class Singleton {

    private volatile static Singleton instance = null;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (null == instance) {
            instance = new Singleton();
        }
        return instance;
    }
}

如果一個對象使用頻率不高,佔用內存還特別大,明顯就不合適用餓漢式了,這時就需要一種懶加載的思想,當程序需要這個實例的時候纔去創建對象,就如同一個人懶的餓到不行了纔去吃東西。


The best investment is to invest in yourself

在這裏插入圖片描述

2020.06.01 記錄辰兮的第73篇博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章