认识设计模式(一)---单例模式(5)
(一)懒汉式(双重检查)
(1)步骤如下:
- 构造器私有化(防止new再获取对象)
- 类的内部创建对象(但是不急着实例化)
- 第一次check:提供一个公有的静态方法,当使用到这个方法时,先判断对象是不是null,加入同步synchronized处理的代码,解决线程安全问题,如果为null再去第二次check
- 第二次check:如果多线程同时进入if语句,这时候再“同步”一次,然后才对象实例化
(2)单例类代码如下:
class Singleton05{
//1-构造器私有化
private Singleton05(){ }
//2-本类内部创建对象实例
private static volatile Singleton05 instance;
//3-提供一个公有的静态方法,当使用到这个方法时,才去创建instance
// 加入同步synchronized处理的代码,解决线程安全问题(同步就是每次只能有一个线程获取)
// 加入双重检查代码,解决线程安全问题,同时解决懒加载问题,同时保证了效率
// 推荐使用
// 懒汉式
public static synchronized Singleton05 getInstance(){
if(instance==null){
synchronized (Singleton05.class){
if(instance==null){
instance=new Singleton05();
}
}
}
return instance;
}
}
(3)测试类代码如下
public class SingletonTest05 {
public static void main(String[] args) {
Singleton05 instance01=Singleton05.getInstance();
Singleton05 instance02=Singleton05.getInstance();
System.out.println(instance01==instance02);
System.out.println("instance01-hashCode="+instance01.hashCode());
System.out.println("instance02-hashCode="+instance02.hashCode());
}
}
(二)优缺点分析
- double-check:是多线程开发中常使用的,进行了两次if检查,就可以保证线程安全了
- 示例代码只有执行一次,后面再次访问时,判断if,直接return实例化对象,也避免反复进行方法同步
- 线程安全:延迟加载,效率较高
- 所以说:在实际开发中,推荐使用这种单例设计模式
(三)与懒汉式(前两个)的区别
- 懒汉式(线程不安全):没使用synchronized,只能在单线程下使用
- 懒汉式(线程安全):使用了synchronized,每次只能一个线程进入if语句,能在多线程下使用,但是效率太低
- 懒汉式(双重检查):使用了两个synchronized,先check进入if语句,再check进行实例化对象
public static synchronized Singleton04 getInstance(){
if(instance==null){
instance=new Singleton04();
}
return instance;
}
改成了
public static synchronized Singleton05 getInstance(){
if(instance==null){
synchronized (Singleton05.class){
if(instance==null){
instance=new Singleton05();
}
}
}
return instance;
}
为什么使用double check?
可能会有多个线程通过第一个if(instance==null)的check,判断对象有没有被实例化,如果没有被实例化就往下走,每个线程会依次获得锁进入临界区。
进入临界区后还要再判断一次单例类是否已被其它线程实例化,如果没有被实例化再进行实例化对象,以避免多次实例化。