美文网首页设计模式
单例模式-Singleton

单例模式-Singleton

作者: 花雨归来 | 来源:发表于2020-04-05 00:31 被阅读0次

1. 说明

目标:单例类只有一个实例。

实现步骤:

  • 构造方法私有化;
  • 单例类自己创建唯一实例;
  • 单例类向外部暴露一个public static方法返回唯一实例。

2. 实现方式

2.1 饿汉式

2.1.1 特点

  • 懒加载:否
  • 线程安全:是
  • 实现难度:易
  • 优点:无锁,运行效率高;
  • 缺点:类加载时就实例化,如果应用程序不使用该类,则造成内存浪费;
  • 原理:只有在类加载到内存时,实例化一次。

注:如果确定某个单例类一定会用到,则推荐使用此种方式。

2.1.2 示例

public class Hungry {
    /**
     * 1. 构造方法私有化
     */
    private Hungry() {
    }

    /**
     * 2. 创建唯一实例
     */
    private static Hungry instance = new Hungry();

    /**
     * 暴露方法给外界
     * @return 唯一实例
     */
    public static Hungry getInstance() {
        return instance;
    }
}

2.2 懒汉式

2.2.1 特点

  • 懒加载:是
  • 线程安全:是
  • 实现难度:易
  • 优点:懒加载,避免内存浪费;
  • 缺点:每次获取都有锁,性能低;
  • 原理:加synchronized锁,多个线程在访问getInstance()方法时,顺序获取到方法锁,进而保证了并发访问时不会多次执行构造方法产生多个实例。

注:不推荐使用。
其他说明:去掉synchronized就是线程不安全的情形,也不推荐使用。

2.2.2 示例

public class LazySafe {
    private LazySafe() {
    }

    private static LazySafe instance;

    public static synchronized LazySafe getInstance() {
        if (instance == null) {
            return new LazySafe();
        }
        return instance;
    }
}

2.3 双重校验锁

2.3.1 特点

  • 懒加载:是
  • 线程安全:是
  • 实现难度:复杂
  • 优点:懒加载,避免内存浪费;双重校验,高性能;
  • 缺点:加volatile关键字,并进行synchronized锁控制,实现复杂;

2.3.2 示例

public class DoubleCheck {
    private volatile static DoubleCheck instance;

    private DoubleCheck() {
    }

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

2.4 静态内部类

2.4.1 特点

  • 懒加载:是
  • 线程安全:是
  • 实现难度:一般
  • 优点:懒加载,性能高,通过静态内部类方式,与双重检查功效类同;

2.4.2 示例

public class InnerStatic {

    private InnerStatic() {
    }

    public static InnerStatic getInstance() {
        return Holder.instance;
    }

    private static class Holder {
        private static final InnerStatic instance = new InnerStatic();
    }
}

2.5 枚举方式

2.5.1 特点

  • 懒加载:否
  • 线程安全:是
  • 实现难度:易
  • 优点:简洁,自动支持序列化机制,绝对防止多次实例化,也是Effective Java 作者 Josh Bloch 提倡的方式,同时可以拒绝反射攻击而创建多个实例;
  • 缺点:非懒加载;

2.5.2 示例

public enum  SingletonEnum {
    INSTANCE;

    // 可以添加任意属性或任意方法
    // 通过SingletonEnum.INSTANCE访问实例,或封装统一命名的getInstance()方法返回实例。

    public static SingletonEnum getInstance() {
        return INSTANCE;
    }
}

3. 总结

一般情况,使用饿汉式即可;如有明确需要懒加载,可使用静态内部类方式;如果涉及到反序列化建议用枚举方式;如果有其他特殊要求,可以考虑双重检查锁的方式。
注:不推荐使用懒汉式,性能存在问题。

相关文章

网友评论

    本文标题:单例模式-Singleton

    本文链接:https://www.haomeiwen.com/subject/qiqephtx.html