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对象序列化ObjectOutputStream和ObjectInputStream示例
5、线程安全 :
在高并发的环境中,getInstance( ) 方法将返回多个指向不同的该类实例。
Thread 1 Thread 21 if (instance == null)
2 if (instance == null)
3 Singleton instance = new Singleton();
4 Singleton instance = new Singleton();
5 return instance;
6 return instance;