设计模式之七种单例模式 发表于 2019-04-21 | 分类于 Java , design patterns 对其中单例模式做个总结,以备不时之需。 饿汉单例模式123456789101112131415161718package singleton;/** * Created by cdx0312 * 2018/3/23 * 饿汉,基于ClassLoader机制避免了多线程的同步问题,加载过程较慢,获取对象速度较快 * 不过instance在类装载时就实例化。虽然大多数情况下调用单例模式的getInstance方法导致类加载,但是也不能确定没有其他 * 静态方法导致类被加载,从而没有达到懒加载的效果。 */public class Singleton { private Singleton() { } private static Singleton singleton = new Singleton(); public static Singleton getInstance() { return singleton; }} 懒汉(线程不安全)1234567891011121314151617181920package singleton;/** * Created by cdx0312 * 2018/3/24 * 懒汉设计模式,线程安全,但是效率很低,每次调用getInstance方法都需要 * 获得锁,而大多数情况下不需要同步 */public class Singleton1 { private Singleton1(){ } private static Singleton1 singleton1; public static synchronized Singleton1 getInstacne(){ if (singleton1 == null) singleton1 = new Singleton1(); return singleton1; }} 懒汉(线程安全)12345678910111213141516171819package singleton;/** * Created by cdx0312 * 2018/3/24 * 懒汉设计模式,线程不安全 */public class Singleton2 { private Singleton2(){ } private static Singleton2 singleton1; public static Singleton2 getInstacne(){ if (singleton1 == null) singleton1 = new Singleton2(); return singleton1; }} 双重检查单例模式1234567891011121314151617181920212223242526272829package singleton;/** * Created by cdx0312 * 2018/3/30 * 双重检查模式,第一次是为了减少不必要的同步,当singleton对象存在时, * 直接返回实例对象,则同步只发生在多个线程同时调用getInstance加载类 * 第二次判空是为了singleton为null才创建实例。 * DCL优点是资源利用率高,第一次执行getInstance时单例对象才被实例化,效率高。 * 缺点是第一次加载速度慢,高并发场景中也会影响其性能,但是也存在DCL失效, * 建议使用静态内部类单例模式来替代DCL */public class Singleton3 { private volatile static Singleton3 singleton; private Singleton3() { } public static Singleton3 getInstance() { if (singleton == null) { synchronized (Singleton3.class) { if (singleton == null) { singleton = new Singleton3(); } } } return singleton; }} 静态内部类12345678910111213141516171819202122package singleton;/** * Created by cdx0312 * 2018/3/30 * 静态内部类单例: * 第一次加载Singleton类时并不会初始化是Instance,只有第一次调用Singleton * 方法时虚拟机加载SingletonHolder并初始化sInstance,这样不仅能确保线程安 * 全也能保证Singleton的唯一性,推荐使用。 */public class Singleton4 { private Singleton4() { } public static Singleton4 getInstance() { return SingletonHolder.sInstance; } private static class SingletonHolder{ private static final Singleton4 sInstance = new Singleton4(); }} 枚举1234567891011121314package singleton;/** * Created by cdx0312 * 2018/3/30 * 默认枚举类实例的创建是线程安全的,并且在任何情况下都是单例,上述的几种 * 单例在反序列化的情况下会创建对象,将一个单例实例对象写到磁盘再读回来, * 从而获得一个实例。反序列化操作提供了 */public enum Singleton5 { INSTANCE; public void doSomething() { }} 容器实现单例1234567891011121314151617181920212223242526272829package singleton;import java.util.HashMap;import java.util.Map;/** * Created by cdx0312 * 2018/3/30 * 使用容器实现单例模式 * 用SingletonManager 将多种的单例类统一管理,在使用时根据key获取对象 * 对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用 * 时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐 * 藏了具体实现,降低了耦合度。 */public class Singleton6 { private static Map<String, Object> objectMap = new HashMap<>(); private Singleton6() { } public static void registerService(String key, Object instance) { if (!objectMap.containsKey(key)) { objectMap.put(key, instance); } } public static Object getService(String key) { return objectMap.get(key); }} Donate comment here 打赏 微信支付 支付宝 比特币