[关闭]
@Yano 2016-07-20T22:26:30.000000Z 字数 3628 阅读 2375

Singleton pattern

Java 设计模式


单例模式网址

Singleton pattern - wikipedia

单例模式定义

在一个系统中,一个类只有一个实例化的对象。

单例模式应用

实现方案

The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object.

可以实现延迟加载,即使用之前不占用内存或资源。(Note the distinction between a simple static instance of a class and a singleton: although a singleton can be implemented as a static instance, it can also be lazily constructed, requiring no memory or resources until needed.)

The singleton pattern must be carefully constructed in multi-threaded applications. If two threads are to execute the creation method at the same time when a singleton does not yet exist, they both must check for an instance of the singleton and then only one should create the new one. If the programming language has concurrent processing capabilities the method should be constructed to execute as a mutually exclusive operation. The classic solution to this problem is to use mutual exclusion on the class that indicates that the object is being instantiated.

Lazy initialization

使用“双重检查加锁”——double-checked locking。其中变量 instance 是 volatile 的,1.4及更早的Java中,volatile关键字的实现会导致双重检查加锁的失效。具体原因,参考 The "Double-Checked Locking is Broken" Declaration

  1. public final class SingletonDemo {
  2. private static volatile SingletonDemo instance;
  3. private SingletonDemo() { }
  4. public static SingletonDemo getInstance() {
  5. if (instance == null ) {
  6. synchronized (SingletonDemo.class) {
  7. if (instance == null) {
  8. instance = new SingletonDemo();
  9. }
  10. }
  11. }
  12. return instance;
  13. }
  14. }

在并发性并不是很高,性能并不特别需求的情况下,可以使用下面简洁的方法:

  1. public final class SingletonDemo {
  2. private static SingletonDemo instance = null;
  3. private SingletonDemo() { }
  4. public static synchronized SingletonDemo getInstance() {
  5. if (instance == null) {
  6. instance = new SingletonDemo();
  7. }
  8. return instance;
  9. }
  10. }

Eager initialization

如果系统总是需要一个实例,或者创建实例的开销并不大,可以使用Eager initialization,它总是返回一个实例。

  1. public final class Singleton {
  2. private static final Singleton INSTANCE = new Singleton();
  3. private Singleton() {}
  4. public static Singleton getInstance() {
  5. return INSTANCE;
  6. }
  7. }

这种方法的好处:

  1. 在类加载之后、被任何线程使用之前,static 的变量 INSTANCE 就已经定义好。
  2. 方法getInstance()不需要同步,所有的线程都会看到同样的实例。
  3. 关键字final使得 INSTANCE 不能修改,保证有且只有一个实例。

Static block initialization

static代码块中创建新实例,同Eager initialization

  1. public final class Singleton {
  2. private static final Singleton instance;
  3. static {
  4. try {
  5. instance = new Singleton();
  6. } catch (Exception e) {
  7. throw new RuntimeException("Darn, an error occurred!", e);
  8. }
  9. }
  10. public static Singleton getInstance() {
  11. return instance;
  12. }
  13. private Singleton() {
  14. // ...
  15. }
  16. }

Initialization-on-demand holder idiom

  1. 尽可能延迟加载
  2. 适用于所有的 Java 版本
  3. 线程安全
  1. public final class Singleton {
  2. // Private constructor. Prevents instantiation from other classes.
  3. private Singleton() { }
  4. private static class SingletonHolder {
  5. private static final Singleton INSTANCE = new Singleton();
  6. }
  7. public static Singleton getInstance() {
  8. return SingletonHolder.INSTANCE;
  9. }
  10. }

内部类SingletonHolder在方法getInstance()被调用时,才会被 class loader 加载。因此这个方法是线程安全的,不需要额外的同步手段。内部类SingletonHolder也可以被定义成final的。

The enum way

In the second edition of his book Effective JavaJoshua Bloch claims that "a single-element enum type is the best way to implement a singleton"  for any language that supports enums, like Java.

  1. public enum Singleton {
  2. INSTANCE;
  3. public void execute (String arg) {
  4. // Perform operation here
  5. }
  6. }

Java语言保证,枚举类型会在需要使用时,通过 class loader 加载。同时 Java 的枚举类型是全局可见的,但是有些呆板 0_o。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注