单例模式.md 3.1 KB

单例模式

什么是单例模式

单例模式确保一个类只有一个实例,并提供一个全局访问点,实现单例模式的方法是私有化构造函数,通过getInstance()方法实例化对象,并返回这个实例

保证在JVM中只有一个实例 幂等

JVM中如何保证实例的幂等问题 保证唯一性

饿汉、懒汉 双重检验

单例模式优缺点

1、单例类只有一个实例

2、共享资源,全局使用

3、节省创建时间,提高性能

缺点:可能存在线程不安全的问题 解决线程安全问题

单例模式应用场景

单例的七种写法

分别是「饿汉」、「懒汉(非线程安全)」、「懒汉(线程安全)」、「双重校验锁」、「静态内部类」、「枚举」和「容器类管理、静态块初始化

单例模式静态内部类为什么线程安全?

参考回答

  • 我们在静态内部类中使用饿汉式方式创建了一个静态常量/变量。
  • JVM保证对于每一个类或接口C,都有一个唯一的初始化锁LC与之对应;保证一个类的类构造器在多线程环境中被正确的加锁、同步。
    • 如果多个线程同时去初始化一个类,那么只有一个线程能获取到初始化锁LC去执行这个类的类构造器。
    • 其他的线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕。
    • 并且每个线程至少获取一次初始化锁LC来确保这个类已经被初始化过了。
  • 以在同一个类加载器下,一个类只会被初始化一次。
  • 而静态属性保证了全局唯一,静态变量初始化保证了线程安全。

注:

  • 一个线程执行类初始化操作,其他线程虽然会被阻塞,但是执行类初始化的线程退出后,其他线程在被唤醒之后不会进入/执行<clinit>()方法。
  • 如果一个类初始化特别慢,就可能造成其他线程阻塞很久,而这种阻塞往往在实际应用中是隐藏的。

枚举类

public enum Color {
    RED("红色"),
    BLUE("蓝色");
    private final String name;
    Color(String name) {
        this.name = name;
    }
    public void add() {
        System.out.println("method add");
    }
}
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
        });
    }
}