单例模式

  1. 懒汉模式
/** * @Description 懒汉模式 实现了延迟加载,但是效率较低 */ public class LazySingleton {private static LazySingleton lazySingleton; private LazySingleton(){}public synchronized static LazySingleton getLazySingleton(){ if(lazySingleton == null){ lazySingleton = new LazySingleton(); } return lazySingleton; }public static void main(String[] args) { LazySingleton h1 = LazySingleton.getLazySingleton(); LazySingleton h2 = LazySingleton.getLazySingleton(); System.out.println(h1==h2); } }

  1. 饿汉模式
1 /** * @Description饿汉模式 * 类加载时完成实例化,避免多线程同步问题 */ public class HungrySingleton {private static HungrySingleton singleton = new HungrySingleton(); private HungrySingleton(){ }public static HungrySingleton getSingleton(){ return singleton; }public static void main(String[] args) { HungrySingleton h1 = HungrySingleton.getSingleton(); HungrySingleton h2 = HungrySingleton.getSingleton(); System.out.println(h1==h2); } }

  1. 双重校验锁模式
/** * @description: 1.懒加载, 2 volatile 保证了指令不会重排 */ public class DoubleCheckSingleton {private volatile static DoubleCheckSingleton singleton; private DoubleCheckSingleton() { }public static DoubleCheckSingleton getInstance(){ if(singleton == null){ synchronized (DoubleCheckSingleton.class){ if(singleton == null){ singleton = new DoubleCheckSingleton(); } } } return singleton; }public static void main(String[] args) { DoubleCheckSingleton d1 = DoubleCheckSingleton.getInstance(); DoubleCheckSingleton d2 = DoubleCheckSingleton.getInstance(); System.out.println(d1==d2); }} singleton = new DoubleCheckSingleton(); 实际过程分为3步 1.为singleton分配内存空间 2.初始化singleton 3.singleton指向分配的内存地址 由于jvm具有指令重排的特性,因此指令可能变成1->3->2。指令重排在单线程下不会出现问题,但多线程环境中会造成一个线程获得没有初始化的实例 使用volatile可以禁止指令重排,在多线程环境下也能正常运行

  1. 内部类模式
/*** * @description: 外部类加载时不会加载内部类,使用内部类时才会加载, 保证了懒加载 * 类加载时实例化对象,不会造成线程安全问题 */ public class InnerClassSingleton {private InnerClassSingleton(){}private static class innerInstance { private static final InnerClassSingleton singleton = new InnerClassSingleton(); }public static InnerClassSingleton getInstance(){ return innerInstance.singleton; }public static void main(String[] args) { InnerClassSingleton i1 = InnerClassSingleton.getInstance(); InnerClassSingleton i2 = InnerClassSingleton.getInstance(); System.out.println(i1==i2); } }

    推荐阅读