jav*_*eek 28 java singleton lazy-initialization
如果单例实现如下,
class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
这个实现与延迟初始化方法有何不同?在这种情况下,将在加载类时创建实例,并且仅在第一次活动使用时加载类本身(例如,当您声明Singleton singleton = null时,不会加载Singleton.getInstance();)
即使使用延迟初始化方法,也会在调用getInstance()时创建实例
我错过了什么吗?
Sau*_*abh 20
使用延迟初始化时,只在需要时才创建实例,而不是在加载类时.所以你逃避了不必要的对象创建.话虽如此,还有其他事情需要考虑.在延迟初始化中,您提供了一个公共API来获取实例.在多线程环境中,它提出了避免不必要的对象创建的挑战.你放置了同步块,这些块会造成不必要的锁定,以检查已经创建的对象.因此在这种情况下它会成为性能问题.
因此,如果您确定创建对象不会占用任何重要的内存并且它几乎总是会在您的应用程序中使用,那么在静态初始化中创建它是件好事.另外,请不要忘记在这种情况下使您的实例成为最终,因为它确保对象创建被正确反映并且总体上反映在多线程环境中重要的主内存.
请参阅IBM关于Singleton + Lazy Loading + Multithreaded Environment案例的本教程
===============编辑于09/09/2018 ====================
您还应该在此处查看按需创建对象模式.
Pri*_*ley 14
您也可以调用任何其他静态方法或静态成员变量来加载单例实例.
class Logger {
private static Logger instance = new Logger();
public static String LOG_LINE_SEPERATOR =
System.getProperty("line.separator");
public static Logger getInstance() {
return instance;
}
public static String logPattern() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
...
Logger.LOG_LINE_SEPERATOR; // load Logger instance or
Logger.logPattern(); // load Logger instance
Run Code Online (Sandbox Code Playgroud)
由于你提到的原因,这只是一种更复杂的做法
enum Singleton {
INSTANCE;
}
Run Code Online (Sandbox Code Playgroud)
使用延迟初始化仅在您担心类可能已初始化但您不想在此时加载单例时才有用.在大多数情况下,这是过度杀戮.
注意:仅引用该类不会初始化该类.
比如说你有一个编写得很糟糕的类,在设置了某些条件之前无法初始化.在这种情况下n必须非零.
public class Main {
public static void main(String ... args) {
Class c= LazyLoaded.class;
System.out.println(c);
}
static class LazyLoaded {
static int n = 0;
static {
System.out.println("Inverse "+1000/n);
}
}
}
Run Code Online (Sandbox Code Playgroud)
版画
class Main$LazyLoaded
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
31733 次 |
| 最近记录: |