单例设计模式:单例模式一共多少种?细分的话可达8种


说到单例模式,大家应该都有所了解,懒汉式、饿汉式马上浮上心头。

那么懒汉式和饿汉式有什么区别?除了常见的两种,还有别的实现单例模式的方法吗?


1、单例模式的概念(个人总结非官方):

  单例顾名思义就是程序运行中,最多只能有一个实例化的对象。(至于为什么这里不做介绍)

2、懒汉式、饿汉式的区别:

  区别实际上体现在加载时间上,饿汉式是在类加载的时候就加载;懒汉式是需要用到该实例时才加载。

   使用饿汉式的话,不管你用不用得到这个实例,它都会在类加载的时候加载;假如我一直没使用到这个实例,是不是就浪费资源了?

   使用懒汉式的话,用到时候才会去加载,资源的利用上更为合理。

   总结:如果确定某个单例一定会用上,饿汉式是一种很合适方法;如果不一定会用的某个单例,懒汉式是比较合适的方法。

2、单例模式的实现

  2.1、饿汉式

    方法1:静态变量方式(线程安全

  /*1.将构造方法私有化,外部无法使用new构造方法创建实例*/
    private Singleton1() {} /*2.内部创建对象*/
    private static Singleton1 instence = new Singleton1(); /*3.对外获取实例的方法*/
    public static Singleton1 getInstence() { return instence; }

 

     方法2:静态代码块方式(线程安全

  /*1.将构造方法私有化,外部无法使用new*/
    private Singleton2() {} /*2.内部静态代码块中创建对象*/
    private static Singleton2 instence; static { instence = new Singleton2(); } /*3.对外获取实例的方法*/
    public static Singleton2 getInstence() { return instence; }

  2.1、懒汉式

    方法3:简单判断非空(多线程并发不安全,单线程无影响

    /*1.将构造方法私有化,外部无法使用new*/
    private Singleton3() {} /*2.创建类成员变量instence*/
    private static Singleton3 instence; /*3.对外获取实例的方法,先判断instence是否为空,为空则创建*/
    public static Singleton3 getInstence() { if(instence == null) { instence = new Singleton3(); } return instence; }

 

    不安全的原因:

 

 

 

 

 

    方法4:synchronized锁方法线程安全但是synchronized锁了整个方法,下一个线程必须等上一个线程释放锁,效率很低,不建议使用

    /*1.将构造方法私有化,外部无法使用new*/
    private Singleton4() {} /*2.创建类成员变量instence*/
    private static Singleton4 instence; /*3.对外获取实例的方法,先判断instence是否为空,为空则创建*/
    public static synchronized Singleton4 getInstence() { if(instence == null) { instence = new Singleton4(); } return instence; }

 

    方法5:同步代码块多线程并发不安全

    /*1.将构造方法私有化,外部无法使用new*/
    private Singleton5() {} /*2.创建类成员变量instence*/
    private static Singleton5 instence; /*3.对外获取实例的方法,先判断instence是否为空,为空则创建*/
    public static Singleton5 getInstence() { if(instence == null) { synchronized (Singleton6.class) { instence = new Singleton5(); } } return instence; }

    不安全原因:与之前的描述一致,虽然它加了锁,但是实际上没有起到作用,如果很多线程已经同时进入if语句块内,结果是一样的。

    方法6:双重检查(线程安全这个方法比较常用   

    /*1.将构造方法私有化,外部无法使用new*/
    private Singleton6() {} /*2.创建类成员变量instence*/
    private static volatile Singleton6 instence; /*3.对外获取实例的方法,双重判断*/
    public static Singleton6 getInstence() { if(instence == null) { synchronized (Singleton6.class) { if (instence == null){ instence = new Singleton6(); } } } return instence; }

 

    方法7:静态内部类(线程安全这个方法比较常用

 

    /*1.将构造方法私有化,外部无法使用new*/
    private Singleton7() {} /*2.编写一个静态内部类*/
    private static class SingletonInstence { private static final Singleton7 INSTENCE = new Singleton7(); } /*3.提供一个静态公有方法,直接返回SingletonInstence*/
    public static Singleton7 getInstence() { return SingletonInstence.INSTENCE; }

 

    方法8:枚举线程安全,还可以防止反序列化重新生成的对象,推荐使用这个方法被大佬推荐使用,至于为啥博主暂时未去了解

     public class Singleton8{ } enum Sing{ insance; public void method(){} }

 

 

 

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM