单例模式

xiaoxiao2025-11-13  5

单例模式

一种设计模式,用该模式设计的类,只能创建出一个实例

场景: Spring: 一个Component就只有一个实例JavaWeb: 一个Servlet只有一个实例文件系统: 一个操作系统只能有一个文件系统

实现

用到较多的单例模式实现方式:饿汉式、懒汉式、双重检测锁、静态内部类。

实现要点: 隐藏构造器static Singleton实例暴露实例的获取方法 追求的目标 线程安全调用效率高延迟加载

1、饿汉式

/** * * @description: 饿汉式 * @author: huang xin * @create: 2018-10-25 20:46 */ public class HungerSingleton { private HungerSingleton(){} //构造函数私有化,不能在类的外部创建该类的实体 /* * 在类加载时候就创建了对象,天然的线程安全 * 问题:没有调用方法创建对象,造成资源浪费 * */ private static final HungerSingleton singleton = new HungerSingleton(); /* * 静态方法直接返回静态变量,方法没有同步(synchronized),调用效率高 * */ public static HungerSingleton getInstance(){ return singleton; } }

2、懒汉式

/** * @description: 懒汉式 * @author: huang xin * @create: 2018-10-25 21:04 */ public class LazySingleton { /* * 懒汉式,顾名思义是类加载是不创建对象,而是调用getInstance()时创建对象 * 问题:需要考虑线程同步,效率低 * */ private LazySingleton(){} //构造器隐藏起来 /* * 类加载时没有初始化,延迟加载 * 不能声明为final,因为getInstance()需要singleton赋值 * */ private static LazySingleton singleton ; /* * 在方法上加上线程同步(synchronized) * 弊端:第二次以后获取单例对象,都要进入锁。耗时 * */ public static synchronized LazySingleton getInstance(){ if (null == singleton){ //第一次创建后,不在创建 singleton = new LazySingleton(); } return singleton; } }

3、双重检测锁

双重检测锁是懒汉式的优化,避免每次实例化都会同步(synchronized)耗时,加入两个if判断。

/** * @description: 双重检测锁,适用于JDK1.5之后的版本 * @author: huang xin * @create: 2018-10-25 21:29 */ public class DoubleCheckSingleton { private DoubleCheckSingleton(){} /* * 需要使用volatile * 保证所有的写(write)都将先行发生于读(read) * */ private static volatile DoubleCheckSingleton singleton; /* * 只在第一次实例化进入锁 * 优点:可以达到延迟加载的要求,调用效率高 * */ public static DoubleCheckSingleton getInstance(){ if (singleton == null){ //第一次检测;存在实例就不进入 synchronized (DoubleCheckSingleton.class){ if (singleton == null){ //第二次检测:防止B线程在获得A线程释放的锁后重入 singleton = new DoubleCheckSingleton(); } } } return singleton; } }

4、静态内部类

/** * @description: 静态内部类实现 * @author: huang xin * @create: 2018-10-25 21:48 */ public class StaticClassSingleton { /* * 外部类没有static属性,因此加载本类时不会立即初始化对象 * */ private static final class InnerClassSingleton{ private static final StaticClassSingleton singleton = new StaticClassSingleton(); } private StaticClassSingleton(){} //构造器隐藏,但内部类可访问的到 /* * 有真正调用getInstance方法时, 才会加载静态内部类(延迟加载), * 而且加载类是天然的线程安全的(线程安全), 没有synchronized(调用效率高) * */ public static StaticClassSingleton getInstance(){ return InnerClassSingleton.singleton; //访问内部类的属性 } }

实现对比

方式优点缺点懒汉式线程安全, 可以延迟加载调用效率不高恶汉式线程安全, 调用效率高不能延迟加载双重检测锁线程安全, 调用效率高, 可以延迟加载、静态内部类线程安全, 调用效率高, 可以延迟加载、
转载请注明原文地址: https://www.6miu.com/read-5039542.html

最新回复(0)