单例模式
描述
控制一个类仅能产生一个实例。
- 懒汉式:类加载时不会生成实例,只有在调用时才会生成实例。
- 饿汉式:类加载时便会生成实例。
类名一般为:xxxSingleton
代码实现示例
/**
* 最优实现:饿汉式-枚举(在Spring环境下)
*/
public enum MySingletonEnum{
INSTANCE;
private MyService myService;
private MySingletonEnum(){
myService = ApplicationContextUtil.getContext().getBean(MyService.class);
}
public String answer(){
return myService.answer();
}
//调用:MySingletonEnum.INSTANCE.answer();
}
/**
* 推荐实现:懒汉式-静态内部类
* 静态内部类的作用是:延迟加载&线程安全
* 因为Singleton被加载时,静态内部类SingletonHolder不会被加载
* 而是等到getUniqueInstance()被调用时,才会被加载。
**/
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}
/**
* 饿汉式-线程安全
**/
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {
}
public static Singleton getUniqueInstance() {
return uniqueInstance;
}
}
/**
* 懒汉式-线程安全-双重校验锁
**/
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
/**
* 懒汉式-线程不安全
**/
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
实际应用场景
FAQ
Spring Bean 实例默认是单例的吗?
Spring Bean实例默认是单例的。
单例类如果不想注册到Spring,但又需要依赖Spring Bean,应该怎么写?
1.使用Spring的ApplicationContext:可以通过ApplicationContext获取Spring Bean实例。 2.使用Spring的依赖注入:可以使用Spring的依赖注入机制,通过构造函数或setter方法注入Spring Bean实例。