我正在尝试用工厂创建一些单例对象:
public class MyObjectFactory {
private MyObject myObject;
public MyObject getInstance(boolean newInstance) {
if (newInstance) {
// return new object
} else {
// return the old object
}
}
}
我想使用 getInstance(boolean newInstance) 方法生成新对象或重用现有的单例对象。
if newInstance 为 true:我将生成一个新的单例对象
if newInstance is false:如果 myObject 为 null,则生成一个新实例并返回,如果 myObject 不为 null,则返回它。
并且这个 getInstance(boolean newInstance) 必须是线程安全的。知道怎么做吗?
根据您的评论,这是实现您想要的内容的一种方法:
public class MyObjectFactory {
private volatile MyObject inst;
public synchronized MyObject getInstance(boolean newInstance) {
if(newInstance) {
inst = new MyObject(...);
}
return inst;
}
}
使该字段为
volatile
意味着该值不会缓存在CPU中,因此所有线程都会立即看到更改。制作方法synchronized
确保只有一个线程可以同时进入。
这不是单例的工作方式。 Singleton 的全部要点是在整个程序中拥有某个类的“单个实例”。参数化工厂方法以获取新实例或前一个实例不属于单例的定义。 最好的单例实现是
Bill Pugh Singleton
:
public class BillPughSingleton {
// Private constructor to force the invocation of getInstance()
private BillPughSingleton() {}
public static BillPughSingleton getInstance() {
return SingletonHelper.INSTANCE;
}
private static class SingletonHelper {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
}
William Pugh Singleton 确保多线程安全并避免急切创建,因为它依赖于嵌套静态类来创建实例。当一个类除了检索单个实例之外还提供多种服务时,此实现非常有用。事实上,如果成员
INSTANCE
是在外部类的类级别声明的,则调用该类的
any方法将导致
INSTANCE
的急切初始化。相反,对于嵌套静态类,静态成员INSTANCE
仅在加载嵌套类时初始化,即当调用方法getInstance()
时,仅根据需要初始化INSTANCE
并使初始化线程安全。 在您的情况下,如果您的类的唯一目的是创建并返回单个实例,您可以使用更简单的实现:
public class SimplerSingleton {
private static SimplerSingleton INSTANCE = new SimplerSingleton();
// Private constructor to force the invocation of getInstance()
private SimplerSingleton() {}
public static SimplerSingleton getInstance() {
return INSTANCE;
}
}
编辑
class MyRetriever {
private static MyClass instance;
//Private constructor to force the factory method invocation
private MyRetriever() {}
//Synchronizing the method in order to avoid race condition and establish a happens-before relationship between threads
public synchronized static MyClass getInstance(boolean flagOverride) {
if (flagOverride || instance == null){
instance = new MyClass();
}
return instance;
}
}