Singleton对象 - 在静态块或getInstance()中;哪个应该用

时间:2014-03-19 05:58:39

标签: java static singleton lazy-initialization static-block

以下是实现单例的两种方法。每种方法的优点和缺点是什么?

静态初始化:

class Singleton {
    private Singleton instance;
    static {
        instance = new Singleton();
    }
    public Singleton getInstance() {
        return instance;
    }
}

延迟初始化是:

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

5 个答案:

答案 0 :(得分:9)

  1. 同步访问者

    public class Singleton {
        private static Singleton instance;
    
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    
    • 懒加载
    • 低绩效
  2. Double Checked Locking&易失性

    public class Singleton {
        private static volatile Singleton instance;
        public static Singleton getInstance() {
            Singleton localInstance = instance;
            if (localInstance == null) {
                synchronized (Singleton.class) {
                    localInstance = instance;
                    if (localInstance == null) {
                        instance = localInstance = new Singleton();
                    }
                }
            }
            return localInstance;
        }
    }
    
    • 懒加载
    • 高性能
    • JDK应该是1.5 ++
  3. On Demand Holder成语

    public class Singleton {
    
        public static class SingletonHolder {
            public static final Singleton HOLDER_INSTANCE = new Singleton();
        }
    
        public static Singleton getInstance() {
            return SingletonHolder.HOLDER_INSTANCE;
        }
    }
    
    • 懒加载
    • 高性能
    • 无法用于非静态类字段

答案 1 :(得分:5)

首先是急切的初始化。 急切初始化甚至在使用之前就会创建实例,这不是最佳实践。

第二个是延迟初始化。 惰性实现在单线程环境中运行良好,但是当涉及到多线程系统时,如果多个线程同时位于if循环内,则会导致问题。它将破坏单例模式,两个线程将获得单例类的不同实例。

请访问:http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-with-examples#static-block-initialization了解更多信息

答案 2 :(得分:1)

让你的班级成为这样的

public class Singleton {

private Singleton() {

}

private static Singleton instance;

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

}

并称之为..

Singleton instance = Singleton.getInstance();

答案 3 :(得分:1)

注意:静态块只能直接访问静态块外部定义的静态变量。要限制为仅创建一个实例的对象应为静态。您的第一个方法在编译期间失败,第二个方法要求您首先创建对象
遵循此方法:

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

确保在其他地方没有创建对象,因此将构造函数更改为private

答案 4 :(得分:0)

静态初始化程序无法引发异常,也不能将RuntimeException吸收到ClassDefNotFoundException中,而不会中断执行。所以你可以看到很多 在您的日志中记录了ClassDefNotFoundException,您甚至可能直到很久以后才意识到出现了问题,因为执行继续。

第二个方法允许RuntimeExceptions停止执行。

更多详细信息在这里: https://twasink.net/2006/07/07/how-not-to-handle-exceptions-from-static-code-block-in-java/