定义:确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例
场景:确保某个类只有一个对象的场景,避免产生多个对象消耗过多资源。如,访问IO、DB等资源时,就要考虑使用单例模式class Singleton1 {// 饿汉式
private static Singleton1 intance = new Singleton1();//直接初始化
private Singleton1() {}
public static Singleton1 getInstance() {
return intance;
}
}
class Singleton2 {// 懒汉式
private static Singleton2 intance;
private Singleton2() {}
public static Singleton2 getInstance() {//用到的时候 才加载
if (intance == null) {
intance = new Singleton2();
}return intance;
}
}
class Singleton3 {// 懒汉式 线程安全
private static Singleton3 intance;
private Singleton3() {}
public synchronized static Singleton3 getInstance() {//用到的时候 才加载, 加锁 多线程调用,都有一个加锁的动作
if (intance == null) {
intance = new Singleton3();
}
return intance;
}
}
class Singleton4 {// 懒汉式 线程安全
private static Singleton4 intance;
private Singleton4() {}
public static Singleton4 getInstance() {//用到的时候 才加载
synchronized (Singleton4.class) {// 加锁
if (intance == null) {
intance = new Singleton4();
}
}
return intance;
}
}
public class Singleton {//双重检查 懒汉式 线程安全
private static Singleton intance;
private Singleton() {}
public static Singleton getInstance() {
if (intance == null) {//检查1:如果为null,再执行到下一步加锁;不为null不执行加锁操作
synchronized (Singleton.class) {//类级锁
if (intance == null) {//检查2:为null,才new一个实例
intance = new Singleton();
}
}
}
return intance;
}
}
静态内部类单例模式: 延迟加载,线程安全
public class StaticInnerClassSingleton implements Serializable {
private StaticInnerClassSingleton() {
}
public static StaticInnerClassSingleton getInstance() {
return Builder.instance;
}
private static class Builder {
private static StaticInnerClassSingleton instance = new StaticInnerClassSingleton();
}
private Object readResolve() throws ObjectStreamException {
return Builder.instance;
}
}
关于函数:readResolve(), 反序列化时的钩子函数,它是私有的,重写防止在反序列化时生成新的实例
以上所有单例方式都有这个问题,严格来说都需要重写
枚举:可以有属性和方法,一个元素的枚举即是单例模式,默认线程安全
public enum SingletonEnum {
INSTANCE_A;
private SingletonEnum() {//构造方法只能是private的,不写也是
id = idGenerate++;
}
public String aa;
public String getAa() {
return aa;
}
private int idGenerate = 1000;
private final int id;
public int getId() {
return id;
}
}