在java中的单身人士

Ish*_*shi 5 java singleton static lazy-loading

我只需要在某处阅读以下代码:

public class SingletonObjectDemo {

    private static SingletonObjectDemo singletonObject;
    // Note that the constructor is private
    private SingletonObjectDemo() {
        // Optional Code
    }
    public static SingletonObjectDemo getSingletonObject() {
        if (singletonObject == null) {
            singletonObject = new SingletonObjectDemo();
       }
       return singletonObject;
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要知道这部分需要什么:

if (singletonObject == null) {
    singletonObject = new SingletonObjectDemo();
}
Run Code Online (Sandbox Code Playgroud)

如果我们不使用这部分代码怎么办?仍然会有一个副本SingletonObjectDemo,为什么我们需要这个代码呢?

pol*_*nts 9

在懒惰与急切初始化

if语句是延迟初始化技术的实现.

更明确的版本如下:

private boolean firstTime = true;
private Stuff stuff;

public Stuff gimmeStuff() {
   if (firstTime) {
      firstTime = false;
      stuff = new Stuff();
   }
   return stuff;
}
Run Code Online (Sandbox Code Playgroud)

什么情况是,在第一次gimmeStuff()被调用时,firstTimetrue,所以stuff会被初始化new Stuff().在随后的调用中,firstTime将是false,因此new Stuff()将不再被调用.

因此,stuff"懒洋洋地"初始化.直到它第一次需要它才真正初始化.

也可以看看


关于线程安全

需要说的是,代码片段不是线程安全的.如果有多个线程,那么在某些竞争条件下 new SingletonObjectDemo()可能会多次调用.

一种解决方案是制造synchronized getSingletonObject()方法.但是,这对所有调用都有一个同步开销getSingletonObject().然后使用所谓的双重检查锁定习惯来试图解决这个问题,但在Java中,这个习惯用法在J2SE 5.0中实际上不起作用volatile,在新的内存模型中引入了关键字.

毋庸置疑,单身模式的正确执行并非易事.

也可以看看

相关问题


有效的Java第二版

以下是本书对这些主题的看法:

第71项:明智地使用延迟初始化

与大多数优化一样,延迟初始化的最佳建议是"除非你需要,否则不要这样做".懒惰的初始化是一把双刃剑.它降低了初始化类或创建实例的成本,但代价是增加了访问延迟初始化字段的成本.根据延迟初始化字段最终需要初始化的部分,初始化它们的成本以及访问每个字段的频率,延迟初始化(就像许多"优化"实际上会损害性能).

在存在多个线程的情况下,延迟初始化很棘手.如果两个或多个线程共享一个延迟初始化的字段,则必须采用某种形式的同步,否则可能导致严重的错误.

在大多数情况下,正常初始化优于延迟初始化.

第3项:使用私有构造函数或enum类型强制执行单例属性

截至1.5发布.实施单例的第三种方法.只需使用一个元素创建一个枚举类型.[...]这种方法在功能上等同于public现场方法,除了它更简洁,提供免费的序列化机制,并提供防止多实例化的铁定保证,即使面对复杂的序列化或基于反射的攻击.

[...]单元素枚举类型是实现单例的最佳方式.

相关问题

关于enum单例/ Java实现:

关于单身模式的优点和替代方案:


sam*_*aur 5

该类有一个SingletonObjectDemo singletonObject包含单例实例的字段.现在有两种可能的策略 -

1 - 您使用声明急切初始化对象 -

private static SingletonObjectDemo singletonObject = new SingletonObjectDemo();
Run Code Online (Sandbox Code Playgroud)

这将导致您的单例对象在加载类时被初始化.这个策略的缺点是,如果你有很多单身人士,他们都会被初始化并占用记忆,即使他们还不需要.

2 - 你做对象的延迟初始化,即在第一次调用时初始化它getSingletonObject()-

// note that this initializes the object to null by default
private static SingletonObjectDemo singletonObject;
Run Code Online (Sandbox Code Playgroud)

...

if (singletonObject == null) {
        singletonObject = new SingletonObjectDemo();
    }
Run Code Online (Sandbox Code Playgroud)

这样可以节省内存,直到真正需要单例.这种策略的缺点是方法的第一次调用可能会看到稍微差一点的响应时间,因为它必须在返回之前初始化obejct.


归档时间:

查看次数:

2664 次

最近记录:

12 年,10 月 前