2012-12-05 118 views
9

我有两个选择:单和公共静态变量的Java

  1. Singleton模式

    class Singleton{ 
        private static Singleton singleton = null; 
    
        public static synchronized Singleton getInstance(){ 
         if(singleton == null){ 
          singleton = new Singleton(); 
         } 
         return singleton; 
        } 
    } 
    
  2. 使用static final

    private static final Singleton singleton = new Singleton(); 
    
    public static Singleton getSingleton() { 
        return singleton; 
    } 
    

请告诉我有什么区别? (单线程或多线程)

更新:我知道Bill Pugh或enum方法。 我不是在寻找正确的方法,但我只使用了1.是否真的有什么区别b/w 1或2?

+0

更新后的问题没有什么区别。 –

+1

这个问题与单身无关。您询问有关从同步/非同步上下文访问静态字段的问题。请编辑标签。 – Juvanis

+0

@BhavikAmbani我不同意,因为第一个选项会锁定试图获取实例的每个线程,因此性能稍差。 –

回答

10

主要区别在于,对于第一个选项,只有在调用getInstance时才会初始化singleton,而使用第二个选项时,只要载入包含的类,它就会初始化。

第三(优选的)选项,这是懒和线程安全是使用一个枚举:

public enum Singleton { 
    INSTANCE; 
} 
+0

我的错误,不知何故错过了它。已经更新了现在的问题。另外,我意识到ENUM单例实例,只是想知道b.w 2的区别,但是非常感谢! – Achow

2

有一点不同:

解决方案1是一个延迟初始化,单个实例将是在getInstance

解决方案2的第一次调用创建是一个渴望初始化,单个实例将被创建时,类loades

他们都是线程安全的,调用第二个多线程是有点误导

+1

那么,我没有把多线程位。它被编辑..:P – Achow

1

因此,随着更新上述两个选项是线程安全的。但​​选项要求每个调用instance的线程获取此锁,从而降低性能,如果这样做很多。此外,在方法级别使用​​可能会存在使用公共可用锁(该类本身)的潜在问题,因此如果某个线程获取了此锁(可能),最终可能会导致死锁。 static final选项更高性能,但不会对单例进行惰性初始化(根据系统情况,这可能不是问题)。

,允许线程安全延迟初始化单例的另一种选择是如下:

public class MySingleton{ 
     private static class Builder{ 
      private static final MySingleton instance = new MySingleton(); 
     } 

     public static MySingleton instance(){ 
      return Builder.intance; 
     } 
} 

此操作,因为执行包含类的任何方法之前静态内部类保证的广告被初始化。

+0

-1选民,照顾澄清推理? –

+0

我刚刚重读了答案,它没有我认为的问题。对不起这个。 :)删除我的-1。答案看起来有点像词沙拉给我,虽然...只是几乎触及真正的差异(懒惰与渴望的初始化)。你提到性能和锁定,但这些并不是主要区别。 – cHao

-1

Java中的单例实现(如果您真的想这样做)可以以比您为急切和懒惰初始化描述的更优雅的方式执行。分别由Joshua Bloch描述的the enum way和由Bill Pugh提出的the SingletonHolder solution

维基百科的文章也是理解模式的好开始,并且回答你的问题。

+1

不回答问题。如果你想提出一个更好的方法,那没问题......但至少在你这样做的时候回答被问到的问题。 – cHao

+0

是啊,你是对的... –

2

第一个解决方案似乎更懒,但实际上并不是。

第一次访问静态方法/字段时会初始化一个类。

很可能getInstance()是该类中唯一可公开访问的静态方法/字段。这是单身人士的观点。

然后,当有人第一次拨打getInstance()时,这个班级被初始化。这意味着两种解决方案在懒惰方面基本相同。

当然,第二种解决方案看起来更好,性能更好。

+0

懒惰的存在,直到getInstance()被显式调用时才创建Singleton的实例。这个类显然会被加载两次。或者我错过了什么?在第二种解决方案中为 – Achow

+1

,实例仅在类初始化时创建;只有在访问静态方法/字段时,即调用getInstance()时,才会初始化类。 – irreputable