【Java设计模式】单例模式

单例设计模式实现

单例设计模式:某个类只能存在一个对象实例
设计要点:java

  • 一个私有构造函数(不能外面new,只能本身建立)
  • 一个私有静态变量(确保只有一个实例)
  • 一个公共静态函数(调用,用来返回实例对象)

饿汉式

天生线程安全,用得也比较多
先建立实例,由于比较饿,没有延迟加载,若是好久没用到这个实例,就会浪费系统资源。spring

静态常量饿汉式

public class Singleton {
    static class Singleton{
        private Singleton(){}
        private final static Singleton instance = new Singleton();
        public static Singleton getInstance() {
            return instance;
        }
    }
}

静态代码块饿汉式

public class Singleton {
    private Singleton() {
    }
    private static Singleton instance;
    static { // 在静态代码块中,建立单例对象
        instance = new Singleton();
    }
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式

用的时候再建立实例,由于比较懒数据库

线程不安全懒汉式

多线程下,一个线程进入了if判断语句块,还将来得及往下执行,另外一个线程也经过了这个判断语句,这时便会产生多个实例。因此在多线程环境下不可以使用这种方式设计模式

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    //提供一个静态的公有方法,当使用到该方法时,才去建立实例
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

线程安全懒汉式

效率低,多线程时,每次都要进行上锁安全

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    //加入同步处理的代码,解决线程安全问题
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

双重检测懒汉式(推荐)

线程安全,懒加载,效率较高springboot

class Singleton {
    private static volatile Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

volatile:保证了变量的可见性,若是发生改变,其余线程立马可见
双重检查:
首次建立实例时,进入第二个if判断后,还未建立实例,此时如有其余线程进来,经过了第一个if判断,而后由于有synchronized,被挡在了外面。
实例化代码只执行一次,后面线程再次访问时,在第一个if判断时,就直接return实例了。多线程

静态内部类

线程安全,推荐使用
静态内部类方式在 Singleton 类被装载时并不会当即实例化,而是在须要实例化时,调用 getInstance 方法,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化.
类的静态属性只会在第一次加载类的时候初始化,因此在这里,JVM 帮助咱们保证了线程的安全性,在类进行初始化时,别的线程是没法进入的。
外部类被加载的时候,静态内部类不会被加载,静态代码块会被加载。函数

public class Singleton {
    private static volatile Singleton instance;
    //构造器私有化
    private Singleton() {}
    //写一个静态内部类,该类中有一个静态属性 Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }
    //提供一个静态的公有方法,直接返回 
    SingletonInstance.INSTANCE
    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

枚举

线程安全,还能防止反射和反序列化从新建立新的对象,不能延时加载工具

enum Singleton {
    INSTANCE; //属性
    public void sayOK() {
        System.out.println("ok");
    }
}

使用场景

须要频繁的进行建立和销毁的对象,好比:工具类对象,频繁访问数据库或文件对象。this

JDK源码Runtime类

饿汉式单例
RunTime表明一个运行环境。每一个JVM进程都是对应这一个Runtime实例,此实例是由JVM为其实例化的。每一个 Java 应用程序都有一个 Runtime 类实例,使应用程序可以与其运行的环境相链接。

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }
     private Runtime() {}
}

Spring依赖注入Bean实例

双重检查懒汉单例

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

SpringBoot源码中的单例

......

相关文章
相关标签/搜索