# 单例模式 ## 什么是单例模式 单例模式确保一个类只有一个实例,并提供一个全局访问点,实现单例模式的方法是私有化构造函数,通过getInstance()方法实例化对象,并返回这个实例 保证在JVM中只有一个实例 幂等 JVM中如何保证实例的幂等问题 保证唯一性 饿汉、懒汉 双重检验 ### 单例模式优缺点 1、单例类只有一个实例 2、共享资源,全局使用 3、节省创建时间,提高性能 缺点:可能存在线程不安全的问题 解决线程安全问题 ## 单例模式应用场景 ## 单例的七种写法 分别是「饿汉」、「懒汉(非线程安全)」、「懒汉(线程安全)」、「双重校验锁」、「静态内部类」、「枚举」和「容器类管理、静态块初始化 ## 单例模式静态内部类为什么线程安全? ### 参考回答 * 我们在静态内部类中使用饿汉式方式创建了一个静态常量/变量。 * JVM保证对于每一个类或接口C,都有一个唯一的`初始化锁LC`与之对应;保证一个类的类构造器在多线程环境中被正确的加锁、同步。 * 如果多个线程同时去初始化一个类,那么只有一个线程能获取到初始化锁LC去执行这个类的类构造器。 * 其他的线程都需要阻塞等待,直到活动线程执行<**clinit**>()方法完毕。 * 并且每个线程至少获取一次初始化锁LC来确保这个类已经被初始化过了。 * 以在同一个类加载器下,一个类只会被初始化一次。 * 而静态属性保证了全局唯一,静态变量初始化保证了线程安全。 注: * 一个线程执行类初始化操作,其他线程虽然会被阻塞,但是执行类初始化的线程退出后,其他线程在被唤醒之后不会进入/执行<**clinit**>()方法。 * 如果一个类初始化特别慢,就可能造成其他线程阻塞很久,而这种阻塞往往在实际应用中是隐藏的。 ## 枚举类 ```java public enum Color { RED("红色"), BLUE("蓝色"); private final String name; Color(String name) { this.name = name; } public void add() { System.out.println("method add"); } } ``` ```java public final class Color extends Enum { public static Color[] values() { return (Color[])$VALUES.clone(); } // 通过名称拿到d public static Color valueOf(String name) { return (Color)Enum.valueOf(com/v8/Color, name); } private Color(String s, int i, String name) { super(s, i); this.name = name; } public void add() { System.out.println("method add"); } public static final Color RED; public static final Color BLUE; private final String name; private static final Color $VALUES[]; // 枚举类初始化常量,没有无参构造函数 // VALUES 存放对象 static { RED = new Color("RED", 0, "\u7EA2\u8272"); BLUE = new Color("BLUE", 1, "\u84DD\u8272"); $VALUES = (new Color[] { RED, BLUE }); } } ```