1.什么是单例模式
单例模式主要用于对象只能被实例化一次的场景。
单例类有几点特征:
- 单例类只能有一个实例
- 单例类只能自己创建这个唯一的实例
- 单例类必须给其他的类提供访问唯一实例的入口。
2.单例模式的几种实现方式
2.1线程安全的懒汉式
2.1.1 Java代码
public class LazyLoadingSingleton {
private static LazyLoadingSingleton instance;
private LazyLoadingSingleton(){}
public synchronized static LazyLoadingSingleton getInstance(){
if(instance == null){
instance = new LazyLoadingSingleton();
}
return instance;
}
}
2.1.2 优缺点
第一次调用才会被初始化,但是加锁影响性能。
2.2线程安全的饿汉式
2.2.1 Java代码
public class HungarySingleton {
private static HungarySingleton instance = new HungarySingleton();
private HungarySingleton(){
}
public static HungarySingleton getInstance(){
return instance;
}
}
2.2.2 优缺点
没有加锁,执行效率高,但是类加载就初始化,浪费内存
2.3双检锁/双重校验锁
2.3.1 java代码
public class DoubleCheckLockSingleton {
private volatile static DoubleCheckLockSingleton instance;
private DoubleCheckLockSingleton(){
}
public static DoubleCheckLockSingleton getInstance(){
if(instance == null){
synchronized (DoubleCheckLockSingleton.class) {
if(instance == null){
instance = new DoubleCheckLockSingleton();
}
}
}
return instance;
}
}
2.3.2 优缺点
在多线程下能保持高性能,但是实现复杂
2.4静态内部类
2.4.1 java代码
public class StaticInnerSingleton {
private StaticInnerSingleton(){
}
public static final StaticInnerSingleton getInstance(){
return InnerSingletonFactory.instance;
}
private static class InnerSingletonFactory{
private static final StaticInnerSingleton instance = new StaticInnerSingleton();
}
}
2.4.2 优缺点
这种方式同样利用了 classloder 机制来保证初始化 instance 时只有一个线程,
它跟双检锁方式不同的是:双检锁方式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),
而这种方式是 StaticInnerSingleton 类被装载了,instance 不一定被初始化。因为 InnerSingletonFactory 类没有被主动使用,只有通过显式调用 getInstance 方法时,
才会显式装载 InnerSingletonFactory 类,从而实例化 instance。
2.5枚举
2.5.1 java代码
public enum EnumSingleton {
INSTANCE;
private Object instance;
EnumSingleton() {
instance = new Object();
}
public Object getInstance() {
return instance;
}
}