设计模式之 Java 中的单例模式(Singleton)

1、单例(Singleton)模式:
2、最简单的单例模式:
3、进阶:
4、延迟创建 :
5、线程安全 :
6、如何创建并发访问效率高的单例 : Double-Check Locking
7、完整的测试用例如下:
8、Initialization on demand holder
9、单例模式序列化应该注意的问题: Singleton 的序列化
10、推荐阅读:

1、单例(Singleton)模式:

保证一个类在系统里只能有一个对象被实例化。

如:缓存池、数据库连接池、线程池、一些应用服务实例等。

难点:在多线程环境中,保证实例的唯一性。

2、最简单的单例模式:

保证该类构造方法是私有的,外部无法创建该类型的对象;

提供一个全局访问点,方便给客户对象提供对此单例对象的使用;

public class Singleton {
    /**
    * 私有变量,外界无法访问
    * 可以定义 public 类型 instance变量,把属性直接暴露给客户对象,则没必要实现getInstance()方法
    * 但是可读性降低,而且直接暴露实例变量的名字给客户程序,会增加代码的耦合度
    */
    private static Singleton instance = new Singleton();
 
    static {
        //...
    }
 
    // 唯一的 private构造方法,客户对象无法创建该对象实例
    private Singleton() {
 
    }
 
    // 全局访问点
    public static Singleton getInstance() {
        return instance;
    }
}
 
// 客户使用单例模式代码
Singleton singleton = Singleton.getInstance();

如果该实例需要比较复杂的初始化过程时,把这个过程应该写在 static{ ... }代码快中。

注意:此实现是线程安全的,当对个线程同时去访问该类的  getInstance( ) 方法时,不会初始化多个不同的对象,这是因为,JVM 在加载此类时,对于 static 属性的初始化只能由一个线程执行且仅一次。

3、进阶:

Statci 在加载类时就会被初始化,出于性能等方面的考虑,我们希望延迟实例化单例对象,只有在第一次使用该类的实例时才去实例化。

4、延迟创建 :

public static Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

我们把单例的实例化过程移至  getInstance( )方法,而不是在加载类时预先创建,当访问此方法时,首先判断该实例是不是已经被实例化过了,如果已被初始化,则直接返回这个对象的引用;否则,创建这个实例并初始化,最后返回这个对象引用。

使用  if (instance == null) 判断是否实例化完成了,此方法不是线程安全的。

编写高质量代码 改善Java程序的151个建议 PDF高清完整版

Java 8简明教程

Java对象初始化顺序的简单验证

Java对象值传递和对象传递的总结

Java对象序列化ObjectOutputStream和ObjectInputStream示例

本文永久更新链接地址

5、线程安全 :

在高并发的环境中,getInstance( ) 方法将返回多个指向不同的该类实例。

    Thread 1   Thread 2  
1   if (instance == null)      
2       if (instance == null)  
3   Singleton instance = new Singleton();      
4       Singleton instance = new Singleton();  
5   return instance;      
6       return instance;  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/e359be4ee4a6ead3de422f3262d72a58.html