[英]Singleton Design Pattern in Java
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
}
在上面的代码中,假设有十个线程正在调用此方法,所有线程都超过了第一个if条件,然后一个线程进入了同步块并创建了实例。 即使创建了实例,剩余的9个线程也将一一出现,它们需要等待并依次通过同步块。 我希望任何线程一旦创建Singleton实例,其他所有线程都不应等待。 告诉我是否有解决方案?
如果您坚持使用惰性实例化,我认为没有解决方案。
您可以在声明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
}
}
您是否测试了性能并得出了确实需要延迟初始化的明确结论? 如果是这样,请使用holder模式 :
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并不是线程安全的。
如果您的10个线程同时使用此Singleton对象,则它将在操作中同时修改该对象的每个线程产生问题。 为了避免这种情况,我们使用了synced关键字,因此一次只有一个线程可以访问Singleton类的对象。 如果您希望所有线程都可以同时访问该对象,请删除sync关键字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.