自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起聊聊Java極簡(jiǎn)設(shè)計(jì)模式:?jiǎn)卫J剑⊿ingleton)

開(kāi)發(fā) 前端
單例設(shè)計(jì)模式(Singleton),多一句沒(méi)有,少一句不行,用最簡(jiǎn)短的篇幅講述設(shè)計(jì)模式最核心的知識(shí),好了,開(kāi)始今天的內(nèi)容??磶讉€(gè)單例對(duì)象的示例代碼,其中有些代碼是線程安全的,有些則不是線程安全的,需要大家細(xì)細(xì)品味,這些代碼也是冰河本人在高并發(fā)環(huán)境下測(cè)試驗(yàn)證過(guò)的。
  • 本章難度:★★☆☆☆
  • 本章重點(diǎn):介紹創(chuàng)建Java單例對(duì)象的七種方式,重點(diǎn)掌握哪些創(chuàng)建方式是線程安全的,哪些方式是線程不安全的,并能夠在實(shí)際項(xiàng)目中靈活運(yùn)用設(shè)計(jì)模式,編寫(xiě)可維護(hù)的代碼。

大家好,我是冰河~~

今天給大家介紹《Java極簡(jiǎn)設(shè)計(jì)模式》的第01章,單例設(shè)計(jì)模式(Singleton),多一句沒(méi)有,少一句不行,用最簡(jiǎn)短的篇幅講述設(shè)計(jì)模式最核心的知識(shí),好了,開(kāi)始今天的內(nèi)容。

單例設(shè)計(jì)模式

看幾個(gè)單例對(duì)象的示例代碼,其中有些代碼是線程安全的,有些則不是線程安全的,需要大家細(xì)細(xì)品味,這些代碼也是冰河本人在高并發(fā)環(huán)境下測(cè)試驗(yàn)證過(guò)的。

  • 代碼一:SingletonExample1

這個(gè)類是懶漢模式,并且是線程不安全的

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 懶漢模式,單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,這個(gè)類是線程不安全的
 */
public class SingletonExample1 {

    private SingletonExample1(){}

    private static SingletonExample1 instance = null;

    public static SingletonExample1 getInstance(){
        //多個(gè)線程同時(shí)調(diào)用,可能會(huì)創(chuàng)建多個(gè)對(duì)象
        if (instance == null){
            instance = new SingletonExample1();
        }
        return instance;
    }
}
  • 代碼二:SingletonExample2

餓漢模式,單例實(shí)例在類裝載的時(shí)候進(jìn)行創(chuàng)建,是線程安全的

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 餓漢模式,單例實(shí)例在類裝載的時(shí)候進(jìn)行創(chuàng)建,是線程安全的
 */
public class SingletonExample2 {

    private SingletonExample2(){}

    private static SingletonExample2 instance = new SingletonExample2();

    public static SingletonExample2 getInstance(){
        return instance;
    }
}
  • 代碼三:SingletonExample3

懶漢模式,單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,這個(gè)類是線程安全的,但是這個(gè)寫(xiě)法不推薦

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 懶漢模式,單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,這個(gè)類是線程安全的,但是這個(gè)寫(xiě)法不推薦
 */
public class SingletonExample3 {

    private SingletonExample3(){}

    private static SingletonExample3 instance = null;

    public static synchronized SingletonExample3 getInstance(){
        if (instance == null){
            instance = new SingletonExample3();
        }
        return instance;
    }
}
  • 代碼四:SingletonExample4

懶漢模式(雙重鎖同步鎖單例模式),單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,但是,這個(gè)類不是線程安全的?。。。。?/p>

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 懶漢模式(雙重鎖同步鎖單例模式)
 *              單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,這個(gè)類不是線程安全的
 */
public class SingletonExample4 {

    private SingletonExample4(){}

    private static SingletonExample4 instance = null;

    //線程不安全
    //當(dāng)執(zhí)行instance = new SingletonExample4();這行代碼時(shí),CPU會(huì)執(zhí)行如下指令:
    //1.memory = allocate() 分配對(duì)象的內(nèi)存空間
    //2.ctorInstance() 初始化對(duì)象
    //3.instance = memory 設(shè)置instance指向剛分配的內(nèi)存
    //單純執(zhí)行以上三步?jīng)]啥問(wèn)題,但是在多線程情況下,可能會(huì)發(fā)生指令重排序。
    // 指令重排序?qū)尉€程沒(méi)有影響,單線程下CPU可以按照順序執(zhí)行以上三個(gè)步驟,但是在多線程下,如果發(fā)生了指令重排序,則會(huì)打亂上面的三個(gè)步驟。

    //如果發(fā)生了JVM和CPU優(yōu)化,發(fā)生重排序時(shí),可能會(huì)按照下面的順序執(zhí)行:
    //1.memory = allocate() 分配對(duì)象的內(nèi)存空間
    //3.instance = memory 設(shè)置instance指向剛分配的內(nèi)存
    //2.ctorInstance() 初始化對(duì)象


    //假設(shè)目前有兩個(gè)線程A和B同時(shí)執(zhí)行g(shù)etInstance()方法,A線程執(zhí)行到instance = new SingletonExample4(); B線程剛執(zhí)行到第一個(gè) if (instance == null){處,
    //如果按照1.3.2的順序,假設(shè)線程A執(zhí)行到3.instance = memory 設(shè)置instance指向剛分配的內(nèi)存,此時(shí),線程B判斷instance已經(jīng)有值,就會(huì)直接return instance;
    //而實(shí)際上,線程A還未執(zhí)行2.ctorInstance() 初始化對(duì)象,也就是說(shuō)線程B拿到的instance對(duì)象還未進(jìn)行初始化,這個(gè)未初始化的instance對(duì)象一旦被線程B使用,就會(huì)出現(xiàn)問(wèn)題。


    public static SingletonExample4 getInstance(){
        if (instance == null){
            synchronized (SingletonExample4.class){
                if(instance == null){
                    instance = new SingletonExample4();
                }
            }
        }
        return instance;
    }
}

線程不安全分析如下:

當(dāng)執(zhí)行instance = new SingletonExample4();這行代碼時(shí),CPU會(huì)執(zhí)行如下指令:

1.memory = allocate() 分配對(duì)象的內(nèi)存空間 2.ctorInstance() 初始化對(duì)象 3.instance = memory 設(shè)置instance指向剛分配的內(nèi)存

單純執(zhí)行以上三步?jīng)]啥問(wèn)題,但是在多線程情況下,可能會(huì)發(fā)生指令重排序。

指令重排序?qū)尉€程沒(méi)有影響,單線程下CPU可以按照順序執(zhí)行以上三個(gè)步驟,但是在多線程下,如果發(fā)生了指令重排序,則會(huì)打亂上面的三個(gè)步驟。

如果發(fā)生了JVM和CPU優(yōu)化,發(fā)生重排序時(shí),可能會(huì)按照下面的順序執(zhí)行:

1.memory = allocate() 分配對(duì)象的內(nèi)存空間 3.instance = memory 設(shè)置instance指向剛分配的內(nèi)存 2.ctorInstance() 初始化對(duì)象

假設(shè)目前有兩個(gè)線程A和B同時(shí)執(zhí)行g(shù)etInstance()方法,A線程執(zhí)行到instance = new SingletonExample4(); B線程剛執(zhí)行到第一個(gè) if (instance == null){處,如果按照1.3.2的順序,假設(shè)線程A執(zhí)行到3.instance = memory 設(shè)置instance指向剛分配的內(nèi)存,此時(shí),線程B判斷instance已經(jīng)有值,就會(huì)直接return instance;而實(shí)際上,線程A還未執(zhí)行2.ctorInstance() 初始化對(duì)象,也就是說(shuō)線程B拿到的instance對(duì)象還未進(jìn)行初始化,這個(gè)未初始化的instance對(duì)象一旦被線程B使用,就會(huì)出現(xiàn)問(wèn)題。

  • 代碼五:SingletonExample5

懶漢模式(雙重鎖同步鎖單例模式)單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,這個(gè)類是線程安全的,使用的是 volatile + 雙重檢測(cè)機(jī)制來(lái)禁止指令重排達(dá)到線程安全

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 懶漢模式(雙重鎖同步鎖單例模式)
 *              單例實(shí)例在第一次使用的時(shí)候進(jìn)行創(chuàng)建,這個(gè)類是線程安全的
 */
public class SingletonExample5 {

    private SingletonExample5(){}

    //單例對(duì)象  volatile + 雙重檢測(cè)機(jī)制來(lái)禁止指令重排
    private volatile static SingletonExample5 instance = null;

    public static SingletonExample5 getInstance(){
        if (instance == null){
            synchronized (SingletonExample5.class){
                if(instance == null){
                    instance = new SingletonExample5();
                }
            }
        }
        return instance;
    }
}
  • 代碼六:SingletonExample6

餓漢模式,單例實(shí)例在類裝載的時(shí)候(使用靜態(tài)代碼塊)進(jìn)行創(chuàng)建,是線程安全的

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 餓漢模式,單例實(shí)例在類裝載的時(shí)候進(jìn)行創(chuàng)建,是線程安全的
 */
public class SingletonExample6 {

    private SingletonExample6(){}

    private static SingletonExample6 instance = null;

    static {
        instance = new SingletonExample6();
    }

    public static SingletonExample6 getInstance(){
        return instance;
    }
}
  • 代碼七:SingletonExample7

枚舉方式進(jìn)行實(shí)例化,是線程安全的,此種方式也是線程最安全的

package io.binghe.concurrency.example.singleton;
/**
 * @author binghe
 * @version 1.0.0
 * @description 枚舉方式進(jìn)行實(shí)例化,是線程安全的,此種方式也是線程最安全的
 */
public class SingletonExample7 {

    private SingletonExample7(){}

    public static SingletonExample7 getInstance(){
        return Singleton.INSTANCE.getInstance();
    }

    private enum Singleton{
        INSTANCE;
        private SingletonExample7 singleton;

        //JVM保證這個(gè)方法絕對(duì)只調(diào)用一次
        Singleton(){
            singleton = new SingletonExample7();
        }
        public SingletonExample7 getInstance(){
            return singleton;
        }
    }
}


責(zé)任編輯:武曉燕 來(lái)源: 冰河技術(shù)
相關(guān)推薦

2023-08-07 08:04:05

動(dòng)態(tài)抽象工廠模式

2024-01-01 08:19:32

模式History前端

2022-01-04 12:08:46

設(shè)計(jì)接口

2021-02-01 10:01:58

設(shè)計(jì)模式 Java單例模式

2023-06-20 07:27:07

架構(gòu)組件插件

2021-03-02 08:50:31

設(shè)計(jì)單例模式

2022-08-26 00:35:31

Java工作流系統(tǒng)

2021-02-07 23:58:10

單例模式對(duì)象

2022-07-29 08:17:46

Java對(duì)象內(nèi)存

2025-03-27 02:00:00

SPIJava接口

2022-07-28 09:44:04

內(nèi)存實(shí)模式保護(hù)模式

2011-07-18 16:51:51

Cocoa 單態(tài) 模式

2012-08-22 10:10:25

單態(tài)單態(tài)設(shè)計(jì)設(shè)計(jì)模式

2024-02-04 12:04:17

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-09-10 21:42:31

2023-06-30 08:18:51

敏捷開(kāi)發(fā)模式

2021-08-27 07:06:10

IOJava抽象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)