簡單了解Java單例模式(Singleton)

http://c.biancheng.net/view/1338.html
https://www.cnblogs.com/zhucj-java/p/13534551.html
https://www.cnblogs.com/restartyang/articles/7770856.html
https://www.imooc.com/article/310708

單例模式定義

單例模式是指一個類只有一個實(shí)例,而且該類可以自己創(chuàng)建自己的實(shí)例啄踊。

單例模式的應(yīng)用

1.在高并發(fā)的系統(tǒng)中生成單號要求唯一袁串,可以將生成單號的實(shí)例寫為單例模式
2.數(shù)據(jù)庫中的連接池
3.枚舉類
4.系統(tǒng)中的上下文
5.spring中@Autowired默認(rèn)注入的是單例注入
6.spring中在需要@Autowired默認(rèn)注入的是多例注入時可在需要注入的類加上@Scope(value="prototype")---prototype原型模式,每次獲取Bean的時候會有一個新的實(shí)例

單例模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1.由于在系統(tǒng)內(nèi)存中只存在一個對象蚊逢,因此可以 節(jié)約系統(tǒng)資源,當(dāng) 需要頻繁創(chuàng)建和銷毀的對象時單例模式無疑可以提高系統(tǒng)的性能。
2.單例模式設(shè)置全局訪問點(diǎn)庭砍,可以優(yōu)化和共享資源的訪問性置。
3.避免對共享資源的多重占用拾并。

缺點(diǎn)

1.單例模式?jīng)]有接口,擴(kuò)展困難鹏浅,則除了修改原來的代碼嗅义,沒有第二種途徑,違背開閉原則隐砸。

單例模式的實(shí)現(xiàn)

分為餓漢式和懶漢式之碗、其中餓漢式在類被加載時就創(chuàng)建了實(shí)例、懶漢式在第一次調(diào)用時創(chuàng)建實(shí)例(在多線程下有線程安全問題)

餓漢式實(shí)現(xiàn)

/**
 * 單例模式-餓漢式
 * 餓漢式不管有沒有調(diào)用getInstance()方法,都會預(yù)先在系統(tǒng)中創(chuàng)建一個靜態(tài)對象
 * 餓漢式優(yōu)點(diǎn): 在多線程模式下是安全的
 * 缺點(diǎn): 沒有調(diào)用方法前就被加載季希,會占用內(nèi)存
 */
public class BaJie extends JPanel {
    private static volatile BaJie instance = new BaJie();

    private BaJie(){
        JLabel j = new JLabel(new ImageIcon("src/main/resources/img/Bajie.jpg"));
        this.add(j);
    }
    public static BaJie getInstance(){
        return instance;
    }

    public static void main(String[] args) {
        JFrame jf = new JFrame("餓漢式單例模式測試");
        jf.setLayout(new GridLayout(1, 2));
        Container contentPane = jf.getContentPane();
        BaJie baJie = BaJie.getInstance();
        contentPane.add(baJie);
        BaJie baJie2 = BaJie.getInstance();
        contentPane.add(baJie2);

        if(baJie == baJie2){
            System.out.println("他們是同一個人");
        } else {
            System.out.println("他們不是同一個人");
        }
        jf.pack();
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

運(yùn)行結(jié)果:

他們是同一個人

懶漢式實(shí)現(xiàn)

為解決在多線程下不安全對創(chuàng)建實(shí)例的方法加鎖synchronized

/**
 * 單例模式--懶漢式
 * 該模式的特點(diǎn)是類加載時沒有生成單例褪那,只有當(dāng)?shù)谝淮握{(diào)用 getlnstance 方法時才去創(chuàng)建這個單例
 * 懶漢式優(yōu)點(diǎn):只有調(diào)用方法才創(chuàng)建對象,不會占用內(nèi)存
 * 缺點(diǎn):在多線程模式下不安全
 */
public class President {

    private static volatile President instance = null;

    //private 避免類在外部被實(shí)例化
    private President(){
        System.out.println("生產(chǎn)一個美國總統(tǒng)");
    }

    /**
     * synchronized為解決多線程下懶漢式存在的線程安全問題
     * synchronized 給對象和方法或代碼塊加鎖式塌,使得同一時刻只有一個線程執(zhí)行該代碼
     * @return
     */
    public static synchronized President getInstance(){
        if (instance == null){
            instance = new President();
        } else {
            System.out.println("已有美國總統(tǒng)博敬,不能再生產(chǎn)!");
        }
        return instance;
    }

    public void getName(){
        System.out.println("獲得一個美國總統(tǒng):特朗普");
    }

    public static void main(String[] args) {

        //線程1
        Thread thread1 = new Thread(){

            @Override
            public void run(){
                President d1 = President.getInstance();
                System.out.println(d1.hashCode());
            }
        };

        thread1.start();

        //線程2
        Thread thread2 = new Thread(){

            @Override
            public void run(){
                President d2 = President.getInstance();
                System.out.println(d2.hashCode());
            }
        };
        thread2.start();
        
        President d3 = President.getInstance();
        System.out.println(d3.hashCode());
    }
}

main執(zhí)行結(jié)果:

生產(chǎn)一個美國總統(tǒng)
338093198
已有美國總統(tǒng)峰尝,不能再生產(chǎn)偏窝!
338093198
已有美國總統(tǒng),不能再生產(chǎn)武学!
338093198

在多線程下通過加鎖可以解決線程安全問題
如果不加synchronized執(zhí)行結(jié)果為:

生產(chǎn)一個美國總統(tǒng)
生產(chǎn)一個美國總統(tǒng)
1587888397
已有美國總統(tǒng)祭往,不能再生產(chǎn)!
1368198263
1587888397

產(chǎn)生了1587888397火窒、1368198263兩個實(shí)例

擴(kuò)展為有限的多例模式Multitcm

生成指定個數(shù)的實(shí)例存到Map中硼补,使用時隨機(jī)取一個使用

有限的多例模式實(shí)現(xiàn)

/**
 * 多例模式Multitcm
 * 維護(hù)一個指定數(shù)量的對象池,當(dāng)請求個數(shù)超過控制的總數(shù)時熏矿,開始循環(huán)重復(fù)使用
 */
public class DuoLi {
    private static int num = 4; //對象數(shù)量
    private static int count = 1; //對象序號
    private static Map<Integer, DuoLi> map = new HashMap();
    static {
        for (int i=1; i<=num; i++){
            map.put(i, new DuoLi());
        }
    }

    private DuoLi(){

    }

    public static DuoLi getInstance(){
        DuoLi duoLi = map.get(count);
        System.out.println(String.format("我是第%s個實(shí)例", count));
        count++;
        if (count > num){
            count = 1;
        }
        return duoLi;
    }

    public static void main(String[] args) {
        for (int i=0; i<5; i++){
            DuoLi duoLi = DuoLi.getInstance();
            System.out.println(duoLi.hashCode());
        }
    }
}

執(zhí)行結(jié)果為

我是第1個實(shí)例
1558600329
我是第2個實(shí)例
636718812
我是第3個實(shí)例
445051633
我是第4個實(shí)例
1051754451
我是第1個實(shí)例
1558600329

第五次取的對象為第一個實(shí)例

剩下的問題

已知類的創(chuàng)建方式有 new括勺,反射、序列化曲掰、克隆
在單例模式由于構(gòu)建方法被私有化不可通過new創(chuàng)建疾捍,那么反射、序列化栏妖、克隆是否可以創(chuàng)建第二個實(shí)例呢乱豆?
https://my.oschina.net/u/3568600/blog/1827375

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吊趾,隨后出現(xiàn)的幾起案子宛裕,更是在濱河造成了極大的恐慌瑟啃,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揩尸,死亡現(xiàn)場離奇詭異蛹屿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)岩榆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門错负,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勇边,你說我怎么就攤上這事瞧捌〖钭拢” “怎么了棕叫?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵耿焊,是天一觀的道長。 經(jīng)常有香客問我奕坟,道長祥款,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任月杉,我火速辦了婚禮刃跛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沙合。我一直安慰自己,他們只是感情好跌帐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布首懈。 她就那樣靜靜地躺著,像睡著了一般谨敛。 火紅的嫁衣襯著肌膚如雪究履。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天脸狸,我揣著相機(jī)與錄音最仑,去河邊找鬼。 笑死炊甲,一個胖子當(dāng)著我的面吹牛泥彤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卿啡,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吟吝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了颈娜?” 一聲冷哼從身側(cè)響起剑逃,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浙宜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蛹磺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粟瞬,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年萤捆,在試婚紗的時候發(fā)現(xiàn)自己被綠了裙品。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡鳖轰,死狀恐怖清酥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蕴侣,我是刑警寧澤焰轻,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站昆雀,受9級特大地震影響辱志,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狞膘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一揩懒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挽封,春花似錦已球、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至点待,卻和暖如春阔蛉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背癞埠。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工状原, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人苗踪。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓颠区,卻偏偏與公主長得像,于是被迫代替她去往敵國和親通铲。 傳聞我的和親對象是個殘疾皇子瓦呼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容