【设计模式之单例模式】(SINGLETON|JAVA)

举报
DevFeng 发表于 2021/12/15 22:51:54 2021/12/15
【摘要】 前言设计模式:主要关注软件系统的设计的设计,与具体语言无关。单例模式:确保一个类只有一个实例,并且提供了对该类的全局访问入口。单例模式属于创建者模式速记关键字:单实例实现恶汉模式 * 恶汉模式 * 类加载到内存后,就实例化一个单例,JVM保证线程安全, 简单实用,推荐使用。 * 唯一缺点:不管加载到与否,类装载时就完成实例化public class Mgr01 { private st...

前言

设计模式:主要关注软件系统的设计的设计,与具体语言无关。

单例模式:确保一个类只有一个实例,并且提供了对该类的全局访问入口。

单例模式属于创建者模式

速记关键字:单实例

实现

恶汉模式

 * 恶汉模式
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全, 简单实用,推荐使用。
 * 唯一缺点:不管加载到与否,类装载时就完成实例化
public class Mgr01 {
    private static  final Mgr01 INSTANCE = new Mgr01();
    //私有化构造方法别人无法使用
    private Mgr01(){};

    //对外提供访问方法
    public static Mgr01 getInstance(){
        return  INSTANCE;
    }

    public static void main(String[] args) {
        Mgr01 instance = Mgr01.getInstance();
        Mgr01 instance1 = Mgr01.getInstance();
        System.out.println(instance == instance1);
    }
}
返回结果为True,证明两个对象是同一个对象

//恶汉2,使用静态语句块完成初始化
public class Mgr02 {
    private static  final Mgr02 INSTANCE ;
    static {
        INSTANCE = new Mgr02();
    }

    private Mgr02(){};

    public static Mgr02 getInstance(){
        return  INSTANCE;
    }

    public static void main(String[] args) {
        Mgr02 instance = Mgr02.getInstance();
        Mgr02 instance1 = Mgr02.getInstance();
        System.out.println(instance == instance1);
    }
}

懒汉模式

 * 用到的时候,才给它初始化
 * 虽然也达到的初始化的目的,却带来了线程不安全的问题
public class Mgr03 {
    private static  Mgr03 INSTANCE ;

    //私有化构造方法别人无法使用
    private Mgr03(){};

    //对外提供访问方法
    public static Mgr03 getInstance(){
        if(INSTANCE==null){
            try {
                //不让它睡,是看不出效果的
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Mgr03();
        }
        return  INSTANCE;
    }

    public static void main(String[] args) {
        //hash码相同也有可能不是同一个对象,同一个类的不同对象它的hash码是不同的。
        for (int i=0; i<100; i++ ){
            new Thread(()->{
                System.out.println(Mgr03.getInstance().hashCode());
            }).start();
        }
    }
}

运行结果:发现并不是所有的实例都是相同的,证明在多线程条件下是不安全的。

16560739
16560739
15565060
15226649
19687554
245682

懒汉模式之线程安全

* 懒汉模式,加锁,双从判断来解决,线程安全问题,加volatile来保证变量的内存可见性, 禁止指令重排序
public class Mgr04 {
    private static volatile Mgr04 INSTANCE ;

    //私有化构造方法别人无法使用
    private Mgr04(){};

    //对外提供访问方法
    public static Mgr04 getInstance(){
        if(INSTANCE==null){
            synchronized (Mgr04.class){
                if(INSTANCE == null){
                    try {
                        //不让它睡,是看不出效果的
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Mgr04();
                }
            }

        }
        return  INSTANCE;

    }

    public static void main(String[] args) {
        //hash码相同也有可能不是同一个对象,同一个类的不同对象它的hash码是不同的。
        for (int i=0; i<100; i++ ){
            new Thread(()->{
                System.out.println(Mgr04.getInstance().hashCode());
            }).start();
        }
    }
}

运行结果

29609474
29609474
29609474
29609474
29609474
29609474
29609474

结论

使用懒汉模式,简单又安全。现在也不用写单例了,因为都交给spring了。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200