1. 简介
单例模式是创建模式中的一种
是一个非常简单的设计模式,
类中只有一个实例,
某些对单例模式的扩展用法中,一个类中会存在多个实例
1.1优点:
- 运行内存中只有固定个数的实例,占用资源少
- 不需要重复实例化和销毁,提高系统性能
1.2缺点:
- 线程不安全,不适用于被频繁修改的对象
- 不方便扩展
1.3使用场景
- 共享的资源: 例如日志,文件等等
- 通用的方法: 例如JSON序列化,加密解密等等
2.实现方式
整体上分为两种
- 饿汉模式: 在类初始化的过程中,就实例化了单例对象,
- 懒汉模式: 在需要使用到单例对象的时候,去实例化单例对象
2.1 饿汉模式
在类进行初始化的过程中,就实例化了单例对象,
可以确保整个内存中只有固定个数对象
public class YanggxSingleton {
/**
* 单例对象
*/
public static final YanggxSingleton instance = new YanggxSingleton();
//私有的构造函数,防止被实例化
private YanggxSingleton() {}
}
2.2 懒汉模式
在需要使用到单例对象的时候,才会实例化对象
有以下几种加载方式
2.2.1 不加锁
线程不安全
在进行instance == null判断的时候,
可能会有多个线程同时返回true,
从而导致多次实例化
public class YanggxSingleton {
// 单例对象
private static YanggxSingleton instance;
// 私有的构造函数,防止被实例化
private YanggxSingleton() {}
/**
* 获取单例对象
* @return
*/
public static YanggxSingleton getInstance() {
if (instance == null) {
instance = new YanggxSingleton();
}
return instance;
}
}
2.2.2 方法上加锁
- 可以确保线程安全
- synchronized锁住了整个方法,执行效率低
public class YanggxSingleton {
// 单例对象
private static YanggxSingleton instance;
// 私有的构造函数,防止被实例化
private YanggxSingleton() {}
/**
* 获取单例对象
* @return
*/
public static synchronized YanggxSingleton getInstance() {
if (instance == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = new YanggxSingleton();
}
return instance;
}
}
2.2.3 双重检查锁
既可以确保线程安全,保证内存中只有一个实例,
又可以保证系统性能,提高运行效率
public class YanggxSingleton {
// 单例对象
private static YanggxSingleton instance;
// 私有的构造函数,防止被实例化
private YanggxSingleton() {}
/**
* 获取单例对象
* @return
*/
public static synchronized YanggxSingleton getInstance() {
//双重检查
if (instance == null) {
synchronized (YanggxSingleton.class) {
//锁住class对象之后
//这里就只有一个线程访问到
//因为instance可能已经被其他线程实例化了
//所以再次判断instance是否为空
//防止多次实例化
if (instance == null) {
instance = new YanggxSingleton();
}
}
}
return instance;
}
}
网友评论