将对象变为单身?

时间:2013-05-22 14:03:03

标签: java design-patterns singleton

我不确定,如果有人之前曾问过这个问题(如果有这样的道歉)。

从维基百科复制的代码。

public class Singleton {
   private static final Singleton instance = new Singleton();

   private Singleton() {}

   public static Singleton getInstance() {
      return instance;
   }
}

它是如何安全的?是(仅)因为这个班级没有变异状态吗?

如果我像这样修改它会发生什么

public class Singleton {
    private static final Singleton instance = new Singleton();
    private FancyClass obj1;
    private FancyClass obj2;

    //feel free to imagine all the getters and setters for obj1 and obj2,
    // like getObj1() and so forth

    //tricky method
    public void doSomething() {
      obj1.destroyEnemy();
      obj2.destroyFriend();
    }

    private Singleton() {
       obj1 = null;
       obj2 = null;
    }

    public static Singleton getInstance() {
      return instance;
    }
}

我对设计模式讨论没兴趣,这是我应该维护的那种代码。假设FancyClass是java标准库类。

,上面的'singleton'线程是安全的

4 个答案:

答案 0 :(得分:3)

你说第一个例子是安全的,这是正确的,因为没有可变状态。

在第二个例子中,单例没有做任何使线程安全的事情,它是否安全取决于FancyClass是否是线程安全的。将synchronized放在doSomething方法上将使其成为线程安全的。

obj1obj2引入getter和setter也有可能产生问题,那些必须与doSomething方法在同一个锁上同步,你会即使FancyClass是线程安全的,也需要锁定,因为如果不同的线程正在改变,那么这些更改需要跨线程可见。

答案 1 :(得分:3)

第一个代码保证调用getInstance()所有线程获得对同一Singleton实例的引用。

对于您的实现(第二个示例),obj1obj2也是如此,因为它们是在创建类本身并且类创建是线程安全的时候创建的(不能是在同一个类加载器中创建两次/“并行”。

doSomething()方法不是线程安全的。如果您需要原子操作,请将其设为synchronized

答案 2 :(得分:1)

Singleton模式根本不是设计为线程安全的,只是为了独特并且禁止创建其他实例。您的代码中唯一的线程安全部分是Singleton实例化private static final Singleton instance = new Singleton();,因为它在类加载时被调用一次。

但实际上,如果您的类中没有成员通过外部系统调用的方法修改,那么您的Singleton将会/保持ThreadSafe

答案 3 :(得分:0)

关于您的代码 - 由于您将构造函数设为私有,因此永远不会调用它。因此将其声明为null是没有意义的。无论如何,实例变量都会自动分配默认值。

首先是第一个代码

   public class Singleton {
   private static final Singleton instance = new Singleton();

   private Singleton() {}

   public static Singleton getInstance() {
      return instance;
   }
}

被称为早期初始化,与延迟初始化不同,在惰性初始化中,只在需要时才创建实例。要使其线程安全,您需要执行以下操作

public class Singleton {
  private static Singleton singleInstance;
    private Singleton() {}
  public static Singleton getSingleInstance() {
    if (singleInstance == null) {
      synchronized (Singleton.class) {
        if (singleInstance == null) {
          singleInstance = new Singleton();
        }
      }
    }
    return singleInstance;
  }

示例是延迟初始化,但概念保持不变。