一. 单例模式 基本概念
二. 单例模式与多线程
一. 单例模式 基本概念
单例模式就是在应用程序中只创建一个该类的对象。又分为饿汉模式和懒汉模式。实现套路也就是只提供私有构造函数,然后提供公有的 getInstance 方法。
- 饿汉模式:也就是一开始就创建该对象。
- 懒汉模式:等到需要用到的时候才创建该对象。
懒汉模式:
饿汉模式:
此时确实能解决问题,但是效率不高,比如说,无论这个对象存不存在,那么都需要加锁解锁,但是道理上应该是创建完后就不需要加锁了。所以有以下改进2。
改进2:
参考:
1. 《剑指 Offer》。
public class Singleton {
private static Singleton singleton;
private Singleton(){};
/**
*
* getInstance:返回单例. <br/>
*
* @author whc
* @return
* @since JDK 1.8
*/
public static Singleton getInstance(){
if(singleton == null)
singleton = new Singleton();
return singleton;
}
}
饿汉模式:
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){};
/**
*
* getInstance:返回单例. <br/>
*
* @author whc
* @return
* @since JDK 1.8
*/
public static Singleton getInstance(){
return singleton;
}
}
二. 单例模式与多线程
其实上面的例子只能使用在单线程下,无法应对多线程环境。比如说如果线程A,B 同时访问到 if(singleton == null) ,那么结果就会创建两个实例,这样就不符合单例模式的思想。
改进1:
此时我们最容易想到 synchronized 关键,这也是最简单的多线程处理,加个关键字完事了,如下:
public static synchronized Singleton getInstance(){
if(singleton == null)
singleton = new Singleton();
return singleton;
}
此时确实能解决问题,但是效率不高,比如说,无论这个对象存不存在,那么都需要加锁解锁,但是道理上应该是创建完后就不需要加锁了。所以有以下改进2。
改进2:
public class Singleton {
private static Singleton singleton;
private static Lock lock = new ReentrantLock();
private Singleton(){};
/**
*
* getInstance:返回单例. <br/>
*
* @author whc
* @return
* @since JDK 1.8
*/
public static Singleton getInstance(){
if(singleton == null){
lock.lock();
try {
if(singleton == null){
singleton = new Singleton();
}
} finally{
lock.unlock();
}
}
return singleton;
}
}
总结:
- 基本概念:分饿汉,懒汉模式。实现:只提供私有构造函数 与 getInstance 方法。
- 普通的单例模式的实现不支持多线程环境,若需支持则要结合 synchronized 或者 lock 等多线程处理方式。
参考:
1. 《剑指 Offer》。