单例设计模式:单例模式一共多少种?细分的话可达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(){}
     }

 

 

 

  

posted @ 2019-08-30 15:40  坤~~  阅读(3973)  评论(2编辑  收藏  举报