前面

主要参考了文章:

  1. 单例模式和多线程安全

http://blog.csdn.net/wuwei1984100/article/details/18979325

  1. Java 单例模式探讨

http://blog.csdn.net/xsl1990/article/details/16359407

饿汉式单例类可以在Java内实现, 但不易在C++ 内实现,因为静态初始化在C++ 里没有固定的顺序,因而静态的m_instance 变量的初始化与类的加载顺序没有保证,可能会出问题。这就是为什么GoF 在提出单例类的概念时,举的例子是懒汉式的。他们的书影响之大,以致Java 语言中单例类的例子也大多是懒汉式的。实际上,本书认为饿汉式单例类更符合Java 语言本身的特点。

Java单例模式相对来说比较简单,也容易理解。我看到的资料将Java单例模式分为了4类。他们分别是:预先加载法,延迟加载法,双重检测(考虑多线程) ,内部类单例(考虑多线程)。

1. 预先加载法

class S1 {

    private S1() {  
        System.out.println("ok1");  
    }  


    private static S1 instance = new S1();  

    public static S1 getInstance() {  
        return instance;  
    }  
}

优点

  • 线程安全的;
  • 在类加载的同时已经创建好一个静态对象,调用时反应速度快。

缺点

  • 资源利用效率不高,可能getInstance永远不会执行到,但是执行了该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化了。

2. 延迟加载法 (考虑多线程)

延迟加载:initialization on demand。

class S2 {  
    private S2() {  
        System.out.println("ok2");  
    }  

    private static S2 instance = null;  

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

优点

  • 资源利用率高,不执行getInstance就不会被实例,可以执行该类其他静态方法。

缺点

  • 第一次加载时发应不快 ,多线程使用不必要的同步开销大。

3. 双重检测(考虑多线程)

双重检测:initialization on demand double check。

class S3 {
    private S3() {
        System.out.println("ok3");
    }

    private static S3 instance = null;

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

优点

  • 资源利用率高,不执行getInstance就不会被实例,可以执行该类其他静态方法。

缺点

  • 第一次加载时发应不快 ,由于java 内存模型一些原因偶尔会失败。

4. initialization on demand holder (考虑多线程)

class S4 {
    private S4() {
        System.out.println("ok4");
    }

    private static class S4Holder {
        static S4 instance = new S4();
    }


    public static S4 getInstance() {
        return S4Holder.instance;
    }
}

优点

  • 资源利用率高,不执行getInstance就不会被实例,可以执行该类其他静态方法。

缺点

  • 第一次加载时发应不快。

总结

一般采用1即可,若对资源十分在意也可考虑4,不要使用2,3了。