Java实现线程安全单例模式的五种方式的示例代码

 更新时间:2022年03月29日 10:31:54   作者:gonghr  
这篇文章主要介绍了Java中实现线程安全单例模式的五种方式:饿汉式、枚举单例、懒汉式、DCL懒汉式和静态内部类懒汉单例,感兴趣的可以了解一下

饿汉式

饿汉式:类加载就会导致该单实例对象被创建

// 问题1:为什么加 final
// 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例
public final class Singleton_hungry implements Serializable {

    // 问题3:为什么设置为私有? 是否能防止反射创建新的实例?
    private Singleton_hungry(){}

    // 问题4:这样初始化是否能保证单例对象创建时的线程安全?
    private static Singleton_hungry INSTANCE = new Singleton_hungry();

    // 问题5:为什么提供静态方法而不是直接将 INSTANCE 设置为 public, 说出你知道的理由
    public static Singleton_hungry getInstance() {
        return INSTANCE;
    }
    public Object readResolve(){  // 防止反射创建新的实例?
        return INSTANCE;
    }
}
  • 问题1:避免子类覆盖父类的一些方法,导致线程不安全。
  • 问题2:实现 readResolve 方法。当从对象流 ObjectInputStream 中读取对象时,会检查对象的类否定义了 readResolve 方法。如果定义了,则调用它返回我们想指定的对象(这里就指定了返回单例对象)。
  • 问题3:防止通过 new 创建对象实例。不能防止反射创建新的实例。
  • 问题4:可以。静态变量初始化在类加载时进行,由 jvm 进行管理,可以保证线程安全。
  • 问题5:通过方法,可以提高拓展性,改进饿汉式转化为懒汉式、利用泛型特性、增加对单例对象的控制操作。

枚举单例

enum Singleton { 
   INSTANCE; 
}

问题1:枚举单例是如何限制实例个数的

单例相当于枚举的静态成员变量,定义几个就有几个实例。

问题2:枚举单例在创建时是否有并发问题

单例相当于枚举的静态成员变量,类加载时初始化,由 jvm 进行管理,可以保证线程安全。

问题3:枚举单例能否被反射破坏单例

不能

问题4:枚举单例能否被反序列化破坏单例

枚举实现了 Serializable 接口,可序列化,但不会被反序列破坏单例。

问题5:枚举单例属于懒汉式还是饿汉式

饿汉式

问题6:枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做

枚举允许构造方法

懒汉式

public final class Singleton_lazy {
    private Singleton_lazy(){}
    private static Singleton_lazy INSTANCE = null;
    // 缺点
    public static synchronized Singleton_lazy getInstance() {
        if(INSTANCE != null) {
            return INSTANCE;
        }
        INSTANCE = new Singleton_lazy();
        return INSTANCE;
    }
}

synchronized 保证线程安全,但锁粒度较大,性能低。

DCL 懒汉式

public final class Singleton_DCL {

    private Singleton_DCL() {}

    // 问题1:解释为什么要加 volatile ?
    private static volatile Singleton_DCL INSTANCE= null;

    // 问题2:对比实现3, 说出这样做的意义
    public static Singleton_DCL getInstance() {
        if(INSTANCE != null) {
            return INSTANCE;
        }
        synchronized (Singleton_DCL.class) {
          
            // 问题3:为什么还要在这里加为空判断, 之前不是判断过了吗
            if(INSTANCE != null) {
                return INSTANCE;
            }
            INSTANCE = new Singleton_DCL();
            return INSTANCE;
        }
    }
}

问题1:避免指令重排序,导致赋值语句先于构造函数执行,得到一个未初始化完毕的对象。

问题2、3:Double Check Lock 机制。同步代码块外部的判断语句主要用于 INSTANCE 初始化并赋值之后,此时 INSTANCE != null,如果有多个线程尝试获取单例,可以提前返回,不用执行同步代码块。而同步代码块内部的判断主要用于第一次初始化时,INSTANCE = null,此时可以有多个线程尝试获取 INSTANCE,只能有一个线程进入同步代码块,其他线程在同步代码块外阻塞,该线程创建一个单例对象之后,唤醒其他线程,再进入同步代码块,发现 INSTANCE != null,则直接返回,不用重新创建单例对象,提高了效率。

静态内部类懒汉单例

public final class Singleton_LazyHolder {
    private Singleton_LazyHolder(){}

    // 问题1:属于懒汉式还是饿汉式
    private static class LazyHolder{
        static final Singleton_LazyHolder INSTANCE = new Singleton_LazyHolder();
    }

    // 问题2:在创建时是否有并发问题
    public static Singleton_LazyHolder getInstance() {
        return LazyHolder.INSTANCE;
    }
}

问题1:懒汉式。静态内部类只有在被方法调用的时候才进行初始化,类加载。

问题2:无,类加载由 jvm 进行,线程安全。

到此这篇关于Java实现线程安全单例模式的五种方式的示例代码的文章就介绍到这了,更多相关Java单例模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Tomcat+JDK安装和配置教程

    Tomcat+JDK安装和配置教程

    这篇文章主要为大家详细介绍了Tomcat+JDK安装和配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • mybatis代码生成+自定义注解+自定义注释实例

    mybatis代码生成+自定义注解+自定义注释实例

    这篇文章主要介绍了mybatis代码生成+自定义注解+自定义注释实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • SpringMVC拦截器实现登录认证

    SpringMVC拦截器实现登录认证

    这篇文章主要介绍了SpringMVC拦截器实现登录认证的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • java如何将实体类转换成json并在控制台输出

    java如何将实体类转换成json并在控制台输出

    这篇文章主要介绍了java如何将实体类转换成json并在控制台输出问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 详解SpringBoot定时任务说明

    详解SpringBoot定时任务说明

    本篇文章主要介绍了详解SpringBoot定时任务说明,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Java如何通过反射获取对象的属性和值

    Java如何通过反射获取对象的属性和值

    这篇文章主要介绍了Java如何通过反射获取对象的属性和值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • Java本地缓存实现代码示例

    Java本地缓存实现代码示例

    这篇文章主要给大家介绍了关于Java本地缓存实现的相关资料,对于缓存的作用不言而喻,可以提高查询效率,比去DB查询的速度要快,文中给出了详细的代码示例,需要的朋友可以参考下
    2023-08-08
  • Java中Session的详解

    Java中Session的详解

    这篇文章主要介绍了了解java中的session的相关问题,什么是session,session怎么用等,具有一定参考价值,需要的朋友可以了解下。
    2021-10-10
  • 出现java.lang.NoSuchMethodException异常的解决(靠谱)

    出现java.lang.NoSuchMethodException异常的解决(靠谱)

    这篇文章主要介绍了出现java.lang.NoSuchMethodException异常的解决方案(靠谱),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • SpringCache缓存自定义配置的实现

    SpringCache缓存自定义配置的实现

    本文主要介绍了SpringCache缓存自定义配置的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01

最新评论