概念:
- 单例模式:
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 - 用处:
有一些对象我们只需要一个,例如:线程池(threadpool),缓存(cache),对话框,注册表(registry)。如果制造出多个实例,就会导致许多问题,例如:程序行为异常,资源使用过量或不一致。
实现:
- 最基本的单例模式:
public class SingletonDemo01 {
//使用静态变量来记录SingletonDemo01的唯一实例
private static SingletonDemo01 singleton;
//创建一个私有的构造器
private SingletonDemo01() {
}
//获取单例对象的方法
public static SingletonDemo01 getInstance(){
//如果对象为空则创建
if(singleton == null) {
singleton = new SingletonDemo01();
}
//返回对象
return singleton;
}
}
- 上面这个单例是线程不安全的,所以需要改进,一共有三种方法:
- 方法一:加上同步实现线程安全:synchronized
public class SingletonDemo01 {
//使用静态变量来记录SingletonDemo01的唯一实例
private static SingletonDemo01 singleton;
//创建一个私有的构造器
private SingletonDemo01() {
}
//获取单例对象的方法 添加了同步锁
public static synchronized SingletonDemo01 getInstance(){
//如果对象为空则创建
if(singleton == null) {
singleton = new SingletonDemo01();
}
//返回对象
return singleton;
}
}
- 方法二:在静态初始化器中构建单件,也叫饿汉式单例
public class SingletonDemo02 {
//在静态初始化器中构建单件 保证了线程安全
private static SingletonDemo02 singleton = new SingletonDemo02();
//私有化构造器
private SingletonDemo02() {};
//返回该类的对象
public static SingletonDemo02 getInstance() {
return singleton;
}
}
- 方法三:双重检查加锁:利用双重检查加锁,首先检查是否实例已经创建,如果尚未创建,才进行同步,这样只会同步一次,大大提升效率
//双重检查加锁 实现单例
public class SingletonDemo03 {
//volatile关键字确保singleton被初始化时,线程正确的处理singleton变量
private volatile static SingletonDemo03 singleton;
private SingletonDemo03(){}
public static SingletonDemo03 getInstance() {
//只同步第一次
if(singleton == null) {
synchronized (SingletonDemo03.class) {
if(singleton == null) {
singleton = new SingletonDemo03();
}
}
}
return singleton;
}
}
总结:
- 如果getInstance() 的性能对应用程序不是很关键,方法一更合适
- 如果程序总是在创建和使用单例,方法二更合适
- 如果想要提升性能,减少同步锁的使用,则方式三更合适