• JAVA设计模式-单例模式


    JAVA设计模式-单例模式

    单例模式

    类只能有一个实例,在内存中会创建并且只创建一次对象。所有其他类或者其他需要调用的地方都是用这一个对象,可以防止频繁创建对象,内存占用高。特点:只能有一个实例,并且能够自行创建这个实例的类。

    实现

    饿汉模式
    写法一
    介绍

    在类的加载时就已经创建好对象,线程是安全的,但是会浪费资源。参考源码:JDK1.8 com.sun.glass.ui.monocle.KeyInput类

    image-20220916180618157

    代码示例
    public class Singleton {
        /**
         * 私有的构造方法,可以防止外部调用时new进行创建对象
         */
        private Singleton(){};
        /**
         * 创建私有的对象
         */
        private static Singleton singleton = new Singleton();
    
        /**
         * 提供公共的对外的获取方法
         * @return
         */
        public static Singleton getInstance(){
            return singleton;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    写法二
    介绍

    在类的加载时就已经创建好对象,此处是使用静态代码块进行创建,线程是安全的。

    image-20220916221335985

    代码示例
    public class Singleton {
    
        /**
         * 私有的构造方法,可以防止外部调用时new进行创建对象
         */
        private Singleton(){};
        /**
         * 创建私有的对象
         */
        private static Singleton singleton = null;
    
        static {
            singleton = new Singleton();
        }
    
        /**
         * 提供公共的对外的获取方法
         * @return
         */
        public static Singleton getInstance(){
            return singleton;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    懒汉模式
    写法一
    介绍

    在第一次使用时进行创建对象,如果多个线程同时调用了getInstance()方法,可能会创建多个对象,线程是不安全的。

    image-20220916182044256

    代码示例
    public class Singleton {
    
        /**
         * 私有的构造方法,可以防止外部调用时new进行创建对象
         */
        private Singleton(){};
        /**
         * 创建私有的对象,注意此处不进行new创建
         */
        private static Singleton singleton;
    
        /**
         * 提供公共的对外的获取方法
         * @return
         */
        public static Singleton getInstance(){
            // 多个线程同时执行这边时,可能会创建多个对象
            if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    写法二
    介绍

    这种写法也是在第一次调用时进行创建对象,但是在该方法上增加了synchronized同步锁,这样就可以保证只会有一个线程执行。线程是安全的,但是synchronized在1.6之前性能比较差,1.6之后进行了优化,性能提升,但是此处为了保证线程安全,使用synchronized,还是多少会影响性能。

    image-20220916215630181

    代码示例
    public class Singleton {
    
        /**
         * 私有的构造方法,可以防止外部调用时new进行创建对象
         */
        private Singleton(){};
        /**
         * 创建私有的对象,注意此处不进行new创建
         */
        private static Singleton singleton;
    
        /**
         * 提供公共的对外的获取方法
         * @return
         */
        public static synchronized Singleton getInstance(){
            // 第一次调用时进行创建对象
            if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    写法三
    介绍

    这种写法采用双重锁的方式,进行判断并创建对象。线程是不安全的。

    image-20220916224546554

    分析线程不安全原因:首先在内存中创建对象,需要进行

    ①分配内存地址

    ②初始化对象

    ③设置对象指向刚刚分配的内存地址

    但是在编译器、指令集并行、内存中都可能进行指令重排序。如果发生指令重排序,对于单线程来说,如果执行①③②和执行①②③的结果是一样的,但是如果是多线程,在线程A执行完①③之后,如果线程B进入到第一个if语句,则会判断singleton已经指向一个地址,不等于null,则直接返回,此时返回的对象是还未进行初始化的空对象。

    代码示例
    public class Singleton {
    
        /**
         * 私有的构造方法,可以防止外部调用时new进行创建对象
         */
        private Singleton(){};
        /**
         * 创建私有的对象,注意此处不进行new创建
         */
        private static Singleton singleton;
    
        /**
         * 提供公共的对外的获取方法
         * @return
         */
        public static Singleton getInstance(){
            if(singleton == null){
                synchronized (Singleton.class){
                    if(singleton == null){
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    写法四
    介绍

    在写法三的基础上,增加volatile,volatile可以禁止指令重排序并且保证共享变量不同线程之间的可见性。

    image-20220916233723442

    代码示例
    public class Singleton {
    
        /**
         * 私有的构造方法,可以防止外部调用时new进行创建对象
         */
        private Singleton(){};
        /**
         * 创建私有的对象,注意此处不进行new创建, 使用volatile
         */
        private volatile static Singleton singleton;
    
        /**
         * 提供公共的对外的获取方法
         * @return
         */
        public static Singleton getInstance(){
            if(singleton == null){
                synchronized (Singleton.class){
                    if(singleton == null){
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    原文链接:https://monkey.blog.xpyvip.top/archives/java-she-ji-mo-shi—dan-li-mo-shi

  • 相关阅读:
    域渗透04-漏洞(CVE-2020-1472)
    pandas算术运算、逻辑运算、统计运算describe()函数、统计函数、累计统计函数及自定义函数运算
    bitmap基础介绍+holo实现离线UV计算
    算法通关村第十六关:黄金挑战:滑动窗口与堆结合
    Speech Recognition模型:Listen, Attend and Spell (LAS)
    【新书推荐】大模型赛道如何实现华丽的弯道超车 —— 《分布式统一大数据虚拟文件系统 Alluxio原理、技术与实践》
    [极客大挑战 2020]Roamphp2-Myblog - 伪协议+文件上传+(LFI&ZIP)||(LFI&Phar)【***】
    ARM开发初级-STM32时钟系统以及如何正确使用HAL_Delay-学习笔记08
    c++初阶-----STL---string的模拟实现
    C专家编程 第1章 C:穿越时空的迷雾 1.8 ANSI C标准的结构
  • 原文地址:https://blog.csdn.net/baidu_23966735/article/details/126911335