Java中的单例设计模式

时间:2011-12-22 05:58:03

标签: java multithreading

Singleton中的Double Lock检查通常写为:

public static Singleton getInstance()
{ 
    if (instance == null)
    {
        synchronized(Singleton.class) {  //1
            if (instance == null)          //2
                  instance = new Singleton();  //3
        }
    }
    return instance; //4
} 

在上面的代码中,假设有10个线程正在调用此方法,所有这些线程都超过了第一个if条件,然后一个线程进入synchronized块并创建实例。即使创建了实例,它们也需要等待并顺序通过synchronized块,剩下的9个线程将逐个出现。我希望只要任何线程创建Singleton实例,所有其他线程就不应该等待。告诉我是否有解决方案吗?

3 个答案:

答案 0 :(得分:8)

如果您坚持使用延迟实例化,我认为没有解决方案。您可以在声明instance变量时创建单例对象:

class Singleton {
    private static final instance = new Singleton();

    private Singleton() {} // prevent outside construction

    public static Singleton getInstance() {
        return instance; // no synchronization needed
    }
}

感谢eSniff的评论(以及yair的评论让我对eSniff的评论说得对),这里是Wikipedia中发布的方法,用于线程安全和懒惰的方法:

class Singleton {
    private static class Holder {
        static final instance = new Singleton();
    }

    private Singleton() {} // prevent outside construction

    public static Singleton getInstance() {
        return Holder.instance; // no synchronization needed
    }
}

答案 1 :(得分:8)

您是否测试了性能并得出了您确实需要延迟初始化的明确结论?如果是这样,请使用持有者模式

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

    private Singleton(){}

    public static Singleton getInstance() { 
        return InstanceHolder.instance;
    }
}

但是,如果你没有经过不错的性能测试,最简单的事情就是在实例声明中初始化单例(急切的初始化),像这样:

public static class Singleton {
    public static Singleton instance = new Singleton();

    private Singleton(){}

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

这两种模式允许依赖类加载过程来确保使用Singleton的任何线程查看一致的实例。这样您就可以获得两个好处:代码更易读,运行速度更快。

顺便说一下,除非Singleton.instance被声明为volatile,否则Double-Check-Idiom不是线程安全的。

答案 2 :(得分:0)

如果您的10个线程同时使用此Singleton对象,那么它将在操作中产生问题,每个线程同时修改此对象。为了避免这种情况,我们使用了synchronized关键字,所以一次只有一个线程可以访问Singleton类的对象。如果您希望所有线程可以同时访问此对象,则删除synchronized关键字。