Java实现单例模式的五种方法介绍

 更新时间:2023年01月31日 10:07:24   作者:Knight_AL  
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例

饿汉式

立即加载

防止new对象,构造私有,写一个公共的方法返回对象

占用空间,线程安全

public class Singleton {
    /**
     * 私有构造
     */
    private Singleton(){
        System.out.println("构造函数Singleton");
    }
    private static Singleton singleton = new Singleton();
    public static Singleton getInstance(){
        return singleton;
    }
}

懒汉式

延迟加载

占用空间小,效率有问题,线程不安全

public class Singleton {
    /**
     * 私有构造
     */
    private Singleton(){
        System.out.println("构造函数Singleton");
    }
    private static Singleton singleton = null;
    public static Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

解决线程安全问题

在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式虽然解决了多个实例对象问题,但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。

锁太大

public class Singleton {
    /**
     * 私有构造
     */
    private Singleton(){
        System.out.println("构造函数Singleton");
    }
    private static Singleton singleton = null;
    public static synchronized Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

双重检查锁

提高同步锁的效率

使用双重检查锁进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。

第一个if判断

第一个线程进来new了Singleton,那么singleton就有值,第二个线程进来,那么进行第一个if判断,不为null,直接返回,不用再去new了,提升了效率

第二个if判断

两个线程同时进来,在synchronized,第一个线程进入,另一个线程等待,第一个线程new Singleton,然后返回,另一个线程发现了第一个线程走了,进入synchronized,如果不进行if判断,那么还会new Singleton,导致线程不安全

public class Singleton {
    /**
     * 私有构造
     */
    private Singleton(){
        System.out.println("构造函数Singleton");
    }
    private static Singleton singleton = null;
    public static synchronized Singleton getInstance(){
        if (singleton == null){  //这个检查是提高效率的
            synchronized (Singleton.class){
                if (singleton == null){
                    singleton = new Singleton();   //这个检查是防止线程安全的
                }
            }
        }
        return singleton;
    }
}

静态内部类

这种方式引入了一个内部静态类(static class),静态内部类只有在调用时才会加载,它保证了Singleton 实例的延迟初始化,又保证了实例的唯一性。它把singleton 的实例化操作放到一个静态内部类中,在第一次调用getInstance() 方法时,JVM才会去加载InnerObject类,同时初始化singleton 实例,所以能让getInstance() 方法线程安全。

特点是:即能延迟加载,也能保证线程安全。

静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。

public class Singleton {
    /**
     * 私有构造
     */
    private Singleton(){
    }
    private static class InnerObject{
        private static Singleton singleton = new Singleton();
    }
    public static synchronized Singleton getInstance(){
        return InnerObject.singleton;
    }
}

内部枚举类实现

防止反射和反序列化攻击

实上,通过Java反射机制是能够实例化构造方法为private的类的。这也就是我们现在需要引入的枚举单例模式。

public class SingletonFactory {
    /**
     * 私有构造
     */
    private enum EnumSingleton{
        SINGLETON;
        private Singleton6 singleton;
        //枚举类的构造方法在类加载是被实例化
        private EnumSingleton(){
            singleton = new Singleton6();
        }
        public Singleton6 getInstance(){
            return singleton;
        }
    }
    public static Singleton6 getInstance(){
        return EnumSingleton.SINGLETON.getInstance();
    }
}
class Singleton6{
    public Singleton6(){
    }
}

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

相关文章

  • Java 从网上下载文件的几种方式实例代码详解

    Java 从网上下载文件的几种方式实例代码详解

    本文通过实例代码给大家介绍了java从网上下载文件的几种方式,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-08-08
  • Java通俗易懂系列设计模式之模板模式

    Java通俗易懂系列设计模式之模板模式

    这篇文章主要介绍了Java通俗易懂系列设计模式之模板模式,想了解设计模式的同学,可以仔细看一下
    2021-04-04
  • 详细解析Java中抽象类和接口的区别

    详细解析Java中抽象类和接口的区别

    这篇文章主要介绍了Java中抽象类和接口的区别详解,需要的朋友可以参考下
    2014-10-10
  • MyBatis找不到mapper文件的实现

    MyBatis找不到mapper文件的实现

    这篇文章主要介绍了MyBatis找不到mapper文件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • SpringBoot使用@EnableAutoConfiguration实现自动配置详解

    SpringBoot使用@EnableAutoConfiguration实现自动配置详解

    你有想过SpringBoot为什么能够自动的帮我们创建一个Bean对象么?或许在我们使用的时候只需要在自己自定义的配置文件中加入@Bean对象就可以,但SpringBoot是如何来创建的呢
    2022-08-08
  • Java实现单词倒序输出

    Java实现单词倒序输出

    这篇文章主要介绍了Java实现单词倒序输出,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-08-08
  • SpringBoot 对象存储 MinIO的详细过程

    SpringBoot 对象存储 MinIO的详细过程

    MinIO 是一个基于 Go 实现的高性能、兼容 S3 协议的对象存储,它适合存储海量的非结构化的数据,这篇文章主要介绍了SpringBoot 对象存储 MinIO,需要的朋友可以参考下
    2023-07-07
  • Java使用Scanner类进行控制台输入实现方法

    Java使用Scanner类进行控制台输入实现方法

    这篇文章主要介绍了Java使用Scanner类进行控制台输入实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • 基于springboot的flowable工作流实战流程分析

    基于springboot的flowable工作流实战流程分析

    这篇文章主要介绍了基于springboot的flowable工作流实战流程分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • Java中图像锐化操作的方法详解

    Java中图像锐化操作的方法详解

    这篇文章主要给大家介绍了关于Java中图像锐化操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11

最新评论