什么是Singleton
某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。例如:JVM运行环境的Runtime类。
要点
只能有一个实例:构造器私有化
必须自行创建这个实例:含有一个该类的静态变量来保存这个唯一的实例
自行向整个系统提供这个实例:对外提供获取该对象实例的方式,直接暴漏或者变量get方法获取
常见形式
- 饿汉式:直接创建对象,不存在线程安全问题
- 直接实例化
- 枚举
- 静态代码块
- 懒汗式:懒加载
- 线程不安全,适用单线程
- 线程安全,适用多线程
- 静态内部类
- 双重锁
代码示例
饿汉式
不管你用不用,在类加载的时候都会直接创建,不存在线程安全问题。
// 类加载的时候直接实例化
public class Singleton {
// 用于存储唯一的实例
public static final Singleton INSTANCE = new Singleton();
// 构造器私有化
private Singleton() {}
}
// 枚举类型的构造器是私有的
public enum Singleton {
INSTANCE
}
// 静态代码块适合复杂初始化,可以加载参数
public class Singleton {
public static final Singleton INSTANCE;
static {
// 这里可以根据实际情况进行拓展,可以传递属性
INSTANCE = new Singleton();
}
}
懒汉式
懒加载,需要的时候才会去初始化对象。
// 线程不安全,适用于单线程
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
// 线程安全
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
synchronized(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
return instance;
}
}
// 双重锁,性能比上一个好
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized(Singleton.class) {
if(instance == null) {
instance == new Singleton();
}
}
}
return instance;
}
}
// 静态内部类,不会随着外部类的加载而初始化,当调用的时候才会加载。
public class Singleton {
private Singleton() {}
private static class Inner {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Inner.INSTANCE;
}
}
总结
懒汉式:静态内部类的形式最简单
饿汉式:枚举类最简单