单例模式详解

只能生成一个实例的类是实现了Singleton(单例)模式的类型。实现单例模式的代码比较短,在面试中经常被提及,这篇随笔介绍几种常见的实现方式。

1.饿汉模式

这种实现方式优点是没有加锁,执行效率高、线程安全的;但是对象在类加载的时候就会被创建,容易产生垃圾对象,正常情况下使用这种方式来创建单例。具体代码如下:

public class Singleton {
    // 构造方法私有化 
    private Singleton(){}
    // 类加载就创建实例
    private static Singleton instance = new Singleton();
    // 对外提供获取实例的方法
    public static Singleton getInstance() {  
        return instance;  
    }  
}

2.懒汉模式

最基本的实现方式,线程不安全。

public class Singleton {
    // 构造方法私有化 
    private Singleton(){}
    // 静态实例
    private static Singleton instance; 
    // 对外提供获取实例的方法,需要的时候再创建实例
    public static Singleton getInstance() {  
        if (instance == null) {
           instance = new Singleton();
        }
        return instance;  
    }  

3.懒汉模式,线程安全

这种模式在 getInstance()方法上加了同步锁,当一个线程获取锁来创建实例,那么其他线程只能等待锁被释放。其中一个线程拿到锁后发现实例已经被创建了,就使用已经创建好的实例,效率较低。两种懒汉模式都不推荐使用。

public class Singleton {
    // 构造方法私有化 
    private Singleton(){}
    // 静态实例
    private static Singleton instance; 
    // 对外提供获取实例的方法,需要的时候再创建实例
    public static synchronized Singleton getInstance() {  
        if (instance == null) {
           instance = new Singleton();
        }
        return instance;  
    }  
}

4.双重校验锁(double-checked locking, DCL)

在实例创建之前我们需要对方法加锁,那么创建以后就无需重复加锁操作,尽最大可能提高程序的执行效率。对上面的代码进行改进,这种方式适用于有特殊需求的场景:

public class Singleton {
    // 构造方法私有化 
    private Singleton(){}
    // 静态实例
    private static volatile Singleton instance; 
    public static Singleton getInstance() {  
        if (instance == null) {
            // 对Singleton类加锁
           synchronized(Singleton.calss) {
               if (instance == null) {
                   instance = new Singleton();
               }
           }
        }
        return instance;  
    }  
}

5.静态内部类

这种方法会在Singleton类内部再创建一个静态内部类,只有显示调用 getInstance()时,实例才会被创建。这种方式适用于静态域需要延迟初始化的场景。

public class Singleton {
     private Singleton (){} 
     private static class SingletonHolder {
         // final修饰,无法再指向其他对象
         private static final Singleton INSTANCE = new Singleton();
     }
    // 锁定方法,防止子类继承重写方法 
     public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

 

参考资料:《Head First 设计模式》

     《剑指offer》第二版

posted @ 2020-07-05 23:11  今天你做题了吗  阅读(115)  评论(0编辑  收藏  举报