• 一文带你了解单例模式


    1.基本介绍

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    2.实现方式

    通常单例模式在Java语言中,有两种构建方式:

    • 懒汉式—线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize之类的锁,以提高性能。
    • 懒汉式—线程安全:加上synchronize之类保证线程安全的基础上的懒汉模式,相对性能很低,大部分时间并不需要同步
    • 饿汉方式。指全局的单例实例在类装载时构建。 [2]
    • 双检锁式。在懒汉式基础上利用synchronize关键字和volatile关键字确保第一次创建时没有线程间竞争而产生多个实例,仅第一次创建时同步,性能相对较高
    • 登记式。作为创建类的全局属性存在,创建类被装载时创建
    • 枚举。java中枚举类本身也是一种单例模式

    K1VK78.png

    三大要素:

    • 私有的构造方法;
    • 指向自己实例的私有静态引用;
    • 以自己实例为返回值的静态的公有方法。

    3.相关实例

    ①饿汉式单例(线程安全)

    阐述:见名知义,“饿汉”说明它很“饥饿”,迫切需要找到吃的,这里也就是我们所说的实例。为什么说它是线程安全的呢?因为我们一开始就创建一个这样的实例,其他线程在访问前这个实例就已经创建完成,在类的生命周期中只创建一次,所以饿汉单例天生就是线程安全的。

    // 饿汉式单例示例
    class Singletone {
    
        private static  Singletone singleton = new Singletone();
    
        // 懒汉式
        private Singletone() {
    
        }
    
        // 保证返回一个实例
        public static Singletone getSingleton() {
            return singleton;
        }
    
    }
    
    
    public class EHanShi {
    
        public static void main(String[] args) {
            Singletone singleton1 = Singletone.getSingleton();
            Singletone singleton2 = Singletone.getSingleton();
            System.out.println(singleton1==singleton2);
    
        }
    }
    

    输出结果为: true

    ②懒汉单例(需要加双重检查锁来保证线程安全)

    阐述: 所谓懒汉模式,就是像一个“懒汉”一样,需要用到创建实例了程序再去创建实例,不需要创建实例程序就“懒得”去创建实例。为什么说它不是线程安全的呢?因为在高并发的情况下懒汉单例就可能创建多个,这样不仅违背了单例的原则,也会在造成使用不同实例造成的线程安全问题,所以懒汉单例需要加锁。

    // 懒汉单例 线程不安全 需要双重检查锁保证在JVM中只能有一个实例
    class Singleton {
    
        // 使用volatile禁止指令重排序
        private static volatile Singleton singleton;
    
        // 懒汉式
        private Singleton() {
    
        }
    
        // 保证返回一个实例
        public static Singleton getSingleton() {
            if (singleton == null) {  // 第一层锁
                synchronized (Singleton.class) {
                    if (singleton == null) { //第二层锁
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    
    }
    
    public class LanHanShi {
        public static void main(String[] args) {
            Singleton s1 = Singleton.getSingleton();
            Singleton s2 = Singleton.getSingleton();
            System.out.println(s1 == s2);
    
        }
    
    }
    

    输出结果为: true

    4.总结

    懒汉式和饿汉式区别点:

    • 饿汉模式是典型的空间换取时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候就不需要再判断了,节省了运行时间。但如果一直没有人调用,这种浪费的空间就不值得,特别是在空间不足的情况下。
    • 懒汉模式是这是一种时间换空间的做法,要想线程安全,大家第一想到的便是下面这种方式,就是在getSingleton方法加上synchronized关键字,但是这种方式也有致命的缺点,那就是并发率太低。
  • 相关阅读:
    慕课网-安卓工程师初养成-6-3 如何使用 Java 中的数组
    慕课网-安卓工程师初养成-6-2 练习题
    慕课网-安卓工程师初养成-6-1 什么是数组
    慕课网-安卓工程师初养成-5-5 进阶练习
    慕课网-安卓工程师初养成-5-4 使用 Eclipse 调试程序
    慕课网-安卓工程师初养成-5-3 编程练习优化
    慕课网-安卓工程师初养成-5-2 编程练习解析
    币种统计
    先取不败游戏
    贪心算法——数列操作得到最大的值
  • 原文地址:https://www.cnblogs.com/charlypage/p/11729288.html
Copyright © 2020-2023  润新知