单例模式是什么?
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式好处
通常使用单例对象都是重量级,里面有很多对象,例如线程池、缓存系统、网络请求等等,很耗资源。使用单例不用重复创建这种对象,其它地方也可以重复使用这个对象,提高性能。
单例模式特征
- 构造方法不对外开发的,一般是private
- 通过一个静态方法或者枚举返回单例类的对象
- 注意多线程的场景
- 注意单例类对象在反序列化时不会重新创建对象
单例模式分类
1. 懒汉式单例
// 懒汉单例,第一次调用时实例化自己
static class Singleton1 {
// 私有的静态变量
private static Singleton1 mInstance = null;
private Singleton1() {
System.out.println("懒汉式单例");
}
// 此时线程不安全,可加synchronize
public static Singleton1 getInstance() {
if (mInstance == null) {
mInstance = new Singleton1();
}
return mInstance;
}
}
2. 饥汉式单例
static class Singleton2 {
private static Singleton2 sInstance = new Singleton2();
private Singleton2() {
}
public static Singleton2 getInstance() {
return sInstance;
}
}
3. 双重检验,DCL
//双重校验,DCL
static class Singleton3 {
// 私有的静态变量
private volatile static Singleton3 mInstance = null;
private Singleton3() {
System.out.println("DCL单例");
}
// 线程安全
public static Singleton3 getInstance() {
if (mInstance == null) {
synchronized (Singleton3.class) {
if (mInstance == null) {
mInstance = new Singleton3();
}
}
}
return mInstance;
}
}
4. 静态内部类单例
//静态内部类单例
static class Singleton4 {
private Singleton4() {
}
private static class Holder{
private static final Singleton4 INSTANCE = new Singleton4();
}
public static Singleton4 getInstance() {
return Holder.INSTANCE;
}
}
5. 枚举单例
static enum Singleton5 {
INSTANCE;
}
6.容器类单例
static class SingletonManager{
private static Map<String, Object> objectMap = new HashMap<>();
public static void registerService(String key, Object instance) {
if (!objectMap.containsKey(key)) {
objectMap.put(key, instance);
}
}
public static Object gerService(String key) {
return objectMap.get(key);
}
}