单例模式
单例模式是Java中最简单的设计模式之一,而且用途也比较多,比如说各种池,回收站等等。单例模式的特点是保证一个类只有一个实例。下面给大家介绍一下常用的单例模式写法。
原文链接:https://blog.csdn.net/qq_35098526/java/article/details/79893628
饿汉式
public class EHanSingletonTest { /** *是否 Lazy 初始化:否 *是否多线程安全:是 *实现难度:易 *描述:这种方式比较常用,但容易产生垃圾对象。 *优点:没有加锁,执行效率会提高。 *缺点:类加载时就初始化,浪费内存。 *它基于 classloder 机制避免了多线程的同步问题, * 不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种, * 在单例模式中大多数都是调用 getInstance 方法, * 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载, * 这时候初始化 instance 显然没有达到 lazy loading 的效果。 */ private static EHanSingletonTest instance = new EHanSingletonTest(); private EHanSingletonTest() { } public static EHanSingletonTest getInstance() { return instance; } }
懒汉式:
public class LHSingletonTest { /** *是否 Lazy 初始化:是 *是否多线程安全:否 *实现难度:易 *描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。 *这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。 */ private static LHSingletonTest instance = null; private LHSingletonTest() { } public static LHSingletonTest getInstance() { if(instance == null) { instance = new LHSingletonTest(); } return instance; } }
双层锁式懒汉式
/** * 双重锁式线程安全的单例模式 */ public class SafeLHSingletonTest { private static volatile SafeLHSingletonTest instance = null; private SafeLHSingletonTest() { } public static SafeLHSingletonTest getInstance() { if(instance == null) { synchronized (instance) { if(instance == null) { instance = new SafeLHSingletonTest(); } } } return instance; } }
特点:
1、使用双层锁式,对比锁住整个方法,这样保证了第二次获取instance有值的时候就不会进入synchronized方法。
2、使用volatile,禁止了重排序,new实例的时候有三个步骤。
1.给instance分配空间、
2.调用 Singleton 的构造函数来初始化、
3.将instance对象指向分配的内存空间(instance指向分配的内存空间后就不为null了);
jvm可能进行重排序,1-3-2,在分配完空间,执行完3,还没执行2,还没初始化完成的时候,线程2就进入了第一个if()判断,然后直接instance不为空,会出现问题。
volatile禁止重排序,保证可见性,每次读取变量都会去主内存中读取最新的变量。
浙公网安备 33010602011771号