GitHub源码分享

微信搜寻:码农StayUp

主页地址:https://gozhuyinglong.github.io

源码分享:https://github.com/gozhuyinglong/blog-demos

1. 单例模式

单例模式(Singleton Pattern)是一种简略的对象创立型模式。该模式保障一个类仅有一个实例,并提供一个拜访它的全局拜访点。

所以要实现单例模式,要做到以下几点:

  • 将构造方法私有化,杜绝应用结构器创立实例。
  • 须要本身创立惟一的一个实例,并提供一个全局拜访入口

2. 单例模式的几种实现

对于单例模式有以下5种实现。

2.1. 懒汉式

该形式是应用synchronized关键字进行加锁,保障了线程安全性。
长处:在第一次调用才初始化,防止了内存节约。
毛病:对获取实例办法加锁,大大降低了并发效率。

因为加了锁,对性能影响较大,不举荐应用。

public class SingletonLazy {    /**     * 公有实例     */    private static SingletonLazy instance;    /**     * 公有构造方法     */    private SingletonLazy() {    }    /**     * 惟一公开获取实例的办法(动态工厂办法),该办法应用synchronized加锁,来保障线程安全性     *     * @return     */    public static synchronized SingletonLazy getInstance() {        if (instance == null) {            instance = new SingletonLazy();        }        return instance;    }}

2.2 饿汉式

饿汉式是利用类加载机制来防止了多线程的同步问题,所以是线程平安的。
长处:未加锁,执行效率高。
毛病:类加载时就初始化实例,造成内存节约。

如果对内存要求不高的状况,还是比拟举荐应用这种形式。

public class SingletonEager {    /**     * 公有实例,动态变量会在类加载的时候初始化,是线程平安的     */    private static final SingletonEager instance = new SingletonEager();    /**     * 公有构造方法     */    private SingletonEager() {    }    /**     * 惟一公开获取实例的办法(动态工厂办法)     *     * @return     */    public static SingletonEager getInstance() {        return instance;    }}

2.3 双重校验锁

利用了volatile修饰符的线程可见性(被一个线程批改后,其余线程立刻可见),即保障了懒加载,又保障了高性能,所以举荐应用。

public class SingletonDCL {    /**     * 公有实例,volatile润饰的变量是具备可见性的(即被一个线程批改后,其余线程立刻可见)     */    private volatile static SingletonDCL instance;    /**     * 公有构造方法     */    private SingletonDCL() {    }    /**     * 惟一公开获取实例的办法(动态工厂办法)     *     * @return     */    public static SingletonDCL getInstance() {        if (instance == null) {            synchronized (SingletonDCL.class) {                if (instance == null) {                    instance = new SingletonDCL();                }            }        }        return instance;    }}

2.4 动态外部类

该模式利用了动态外部类提早初始化的个性,来达到与双重校验锁形式一样的性能。因为须要借助辅助类,并不罕用。

public class SingletonInnerClass {    /**     * 公有构造方法     */    private SingletonInnerClass() {    }    /**     * 惟一公开获取实例的办法(动态工厂办法)     *     * @return     */    public static SingletonInnerClass getInstance() {        return LazyHolder.INSTANCE;    }    /**     * 公有动态外部类     */    private static class LazyHolder {        private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();    }}

2.5 枚举类

该形式利用了枚举类的个性,不仅能防止线程同步问题,还避免反序列化从新创立新的对象。这种形式是 Effective Java 作者 Josh Bloch 提倡的形式。

但因为这种编码方式还不能适应,所以理论工作中很少应用。

public enum SingletonEnum {    INSTANCE;    public void method() {        System.out.println("枚举类中定义方法!");    }}