2016-03-08 71 views
2

我在看电报的信使源代码,我注意到他们的单例类在它们的getInstance方法中都使用局部变量,就像下面一样。例如,在他们的Android GitHub repo,对NotificationsController.java类,他们有以下几点:Singleton - 实例化类的最佳方式

private static volatile NotificationsController Instance = null; 
public static NotificationsController getInstance() { 
    NotificationsController localInstance = Instance; 
    if (localInstance == null) { 
     synchronized (MessagesController.class) { 
      localInstance = Instance; 
      if (localInstance == null) { 
       Instance = localInstance = new NotificationsController(); 
      } 
     } 
    } 
    return localInstance; 
} 

我不完全知道什么是局部变量“localInstance”存在的目的。任何人都可以解释“localInstance”var的目的究竟是什么?如果没有它,就不能实现,就像在下面的代码中一样?

private static volatile NotificationsController Instance = null; 
public static NotificationsController getInstance() { 
    if (Instance == null) { 
     synchronized (MessagesController.class) { 
      if (Instance == null) { 
       Instance = new NotificationsController(); 
      } 
     } 
    } 
    return Instance; 
} 
+1

在你的版本,你也缺少第二个'if'检查'synchronized'块内。这意味着构造函数可能会被调用两次。 – Thilo

+0

对我来说只是看起来不好的代码。对于初学者单身模式以上是反模式http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons。其次,他们正在同步一个不同类的类对象,如果有其他代码决定对该对象进行锁定,则可能导致死锁,第三,您提出的观点。 GitHub只有一个主要贡献者。我会犹豫使用那个库。 – Samuel

回答

1

这是出于性能原因而完成的。

考虑变量初始化时最常见的情况。写入的代码将读取一次volatile变量并返回值。你的版本会读两次。由于易失性读取带来轻微的性能成本,因此使用本地变量可能会更快。

因为在你的情况下,懒惰初始化变量是静态的,所以最好使用持有者类成语。以this answer为例。

相关问题