Head First 设计模式--Singleton

chapter 5 --单件模式

                                  独一无二的对象

 

1. 如果我们不需要这个实例,它就永远不会产生,这就是“延迟实例化”。

 

2. 单件常被用来管理共享的资源,例如数据库连接或线程池。

 

3. 外界必须“请求”得到一个实例,而不是自行实例化得到一个实例。

 


单件模式:

确保一个类只有一个实例,并提供一个全局访问点

 

Singleton

Structure

这个uniqueInstance类变量持有唯一的单件实例。getInstance()方法是静态的,这意味着它是一个类方法,所以可以在代码的任何地方使用Singleton.getInstance()访问它。这和访问全局变量一样简单,只是多了一个优点:单件可以延迟实例化。单件模式的类也可以是一般的类,具有一般的数据和方法。

 

Singleton模式的代码:

 

public class Singleton {
    private static Singleton uniqueInstance;

    private Singleton() {}

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

}
  

通过增加synchronized关键字到getInstance()方法中,我们迫使每个进程在进入这个方法之前,要先等候别的线程离开该方法。即不会有两个线程可以同时进入这个方法。

 

但是,只有第一次执行此方法时,才真正需要同步。一旦设置好uniqueInstance变量,实际上就不再需要同步这个方法了。之后的每次调用,同步都是一种累赘。可从使用以下来改善多线程的性能:

  • 如果getInstance()的性能对应用程序不是很关键,就什么都别做。
  • 使用“急切”创建实例,而不用延迟实例化的做法。
  • 用“双重检查加锁”,在getInstance()中减少使用同步。

双重检查加锁代码:

 

public class Singleton {
    private volatile static Singleton uniqueInstance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
             }
         }
         return uniqueInstance;
    }
}

 volatile关键词确保,当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地处理uniqueInstance变量。

 

 

本章小结:

  • 单件模式确保程序中一个类最多只有一个实例。
  • 单件模式也提供访问这个实例的全局点。
  • 在Java中实现单件模式需要私有的构造器、一个静态方法和一个静态变量。
  • 确定在性能和资源上的限制,然后小心地选择适当的方案来实现单件,已解决多线程的问题。
  • 如果不是采用第五版的Java 2,双重检查加锁实现会失效。
  • 如果你使用多个类加载器,可能会导致单件失效而产生多个实例。
  • 如果使用JVM 1.2或之前的版本,你必须建立单件注册表,以免垃圾收集器将单件回收。

你可能感兴趣的:(设计模式,jvm,多线程)