回顾一下单例模式

简介: 回顾一下单例模式

   在Java的23中设计模式中,单例模式是最简单也是最常考的一个设计模式,实现单例模式的方式有很多种,而且有的实现方式会考虑线程安全和反射机制的破坏,其中最常见的不外乎懒汉模式饿汉模式双重检查式枚举式,加下来就每个方式的单例模式进行代码的实现,以此来做一个对比。

1 懒汉模式

      顾名思义,懒汉就是在需要的时候去做事情,因此懒汉模式就是在需要的时候再去new,进行对象的实例化,等再次需要时先进行检查,如果对象不为空就直接返回。

/**
 * 懒汉式
 *
 * @author 17122
 */
public class LanHanSingleton {
    /**
     * 先声明,不需要new
     */
    private static LanHanSingleton instance;
    /**
     * 构造方法私有,不允许new
     */
    private LanHanSingleton() {
    }
    /**
     * 多线程环境下加入synchronized可保障线程安全
     *
     * @return
     */
    public static synchronized LanHanSingleton getInstance() {
        //检查如果对象为空则重新创建
        if (instance == null) {
            instance = new LanHanSingleton();
        }
        return instance;
    }
}
复制代码


2 饿汉模式

      可以把饿汉当做JVM的类加载器,而需要实例化的对象就是食物,当在JVM类加载时就迫切的进行类的实例化,因此饿汉模式名由此而生。简单的描述就是在类加载时将对象实例化,获取时直接返回。

/**
 * 饿汉式单例
 *
 * @author 17122
 */
public class EHanSingleton {
    /**
     * 初始化类时先创建实例
     */
    private static EHanSingleton instance = new EHanSingleton();
    /**
     * 构造方法私有,不允许new
     */
    private EHanSingleton() {
    }
    public static EHanSingleton getInstance() {
        //返回实例
        return instance;
    }
}
复制代码


3 双重检查式

      双重检查式的实现主要是为了多线程下的安全状态,放在多个线程在第一次if判断时产生相同的结果。而且在第一次if之后加入了对象锁,确保多线程下线程的安全。

/**
 * 双重检查式
 *
 * @author 17122
 */
public class DoubleCheckSingleton {
    /**
     * volatile保证多线程下数据的可见性
     */
    private volatile static DoubleCheckSingleton singleton;
    /**
     * 构造方法私有,不允许new
     */
    private DoubleCheckSingleton() {
    }
    public static DoubleCheckSingleton getSingleton() {
        //第一次检查
        if (singleton == null) {
            //加入对象锁
            synchronized (DoubleCheckSingleton.class) {
                //第二次检查
                if (singleton == null) {
                    singleton = new DoubleCheckSingleton();
                }
            }
        }
        return singleton;
    }
}
复制代码


4 枚举式

      这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。

/**
 * 枚举式
 *
 * @author 17122
 */
public enum EnumSingleton {
    INSTANCE;
    /**
     * 返回实例
     *
     * @return
     */
    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
    //以下可以时任意方法
}
复制代码


5 对比

是否线程安全 是否能被反射破坏 多线程下使用效率
懒汉模式 较低
饿汉模式 较高
双重检查式 较高
枚举式 较高

6 扩展:反射如何破坏单例?

/**
 *  反射破坏单例模式
 */
try {
    DoubleCheckSingleton singleton = DoubleCheckSingleton.getSingleton();
    Constructor<DoubleCheckSingleton> constructor = DoubleCheckSingleton.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    DoubleCheckSingleton instance = constructor.newInstance();
    System.out.println("反射破坏单例:");
    System.out.println(singleton == instance);
} catch (Exception e) {
    e.printStackTrace();
}



相关文章
|
9月前
|
设计模式 安全 测试技术
【C++】—— 单例模式详解
【C++】—— 单例模式详解
110 0
|
9月前
|
设计模式 安全
详细讲解什么是单例模式
详细讲解什么是单例模式
|
2月前
|
设计模式 安全 C#
单例模式详解
单例模式是一种常用的创建型设计模式,确保某个类只有一个实例,并提供一个全局访问点。本文详细介绍了单例模式的定义、特点、适用场景、优缺点及实现代码(C++ 和 C#),并探讨了线程安全的实现细节和与依赖注入的结合使用。
54 0
|
9月前
|
设计模式
单例模式
单例模式
51 0
|
设计模式 安全 编译器
2023-6-12-第三式单例模式
2023-6-12-第三式单例模式
92 0
|
9月前
|
安全 C++
C++单例模式
C++单例模式
62 1
找对象需要单例模式吗?
单例模式的类只提供私有的构造函数
|
SQL 安全 Java
五种单例模式介绍
五种单例模式介绍
100 0
|
设计模式 缓存 JSON
没那么简单的单例模式
没那么简单的单例模式
140 0
没那么简单的单例模式
|
存储 安全 调度
单例模式的简单介绍
单例模式的简单介绍

热门文章

最新文章