E.g我的课程Singleton
包含静态字段instance
:
public class Singleton {
private static Singleton instance;
// other code, construct, getters, no matter
}
我可以使用两个不同的类加载器加载此类两次。我怎么能避免它?这是不安全和危险的。
另外,如果我将instance设置为null,它是否会为这两个类设置为null?
Singleton singleton = Singleton.getInstance();
singleton = null;
答案 0 :(得分:26)
如果你想在类加载器中使用真正的Singleton
,那么你需要一个共同的父来加载有问题的类,或者你需要自己指定类加载器。
更新:根据@Pshemo的评论,下面博客中的一些内容可能直接来自JavaWorld Article。我已离开博客条目,因为它可能仍然可以帮助某人,但它值得知道内容最初来自哪里。
<强>原始强> 有一个blog条目为您提供了一种方法来实现这一目标&#34; (虽然我还没试过!),看起来相当合理
根据以下要求,我上面的链接提供了一个代码段 - 我建议您访问博客,但需查看完整背景信息:
private static Class getClass(String classname) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader == null)
classLoader = Singleton.class.getClassLoader();
return (classLoader.loadClass(classname));
}
答案 1 :(得分:1)
这是一个黑客滥用Properties
扩展Map
的事实,这是一个古老的不幸的设计决定。
public final class JvmWideSingleton
{
private static final JvmWideSingleton INSTANCE;
static {
// There should be just one system class loader object in the whole JVM.
synchronized(ClassLoader.getSystemClassLoader()) {
Properties sysProps = System.getProperties();
// The key is a String, because the .class object would be different across classloaders.
JvmWideSingleton singleton = (JvmWideSingleton) sysProps.get(JvmWideSingleton.class.getName());
// Some other class loader loaded JvmWideSingleton earlier.
if (singleton != null) {
INSTANCE = singleton;
}
else {
// Otherwise this classloader is the first one, let's create a singleton.
// Make sure not to do any locking within this.
INSTANCE = new JvmWideSingleton();
System.getProperties().put(JvmWideSingleton.class.getName(), INSTANCE);
}
}
}
public static JvmWideSingleton getSingleton() {
return INSTANCE;
}
}
这可以进行参数化,但是初始化将是惰性的并转到getSingleton()
。
Properties
基于Hashtable
,所以它是线程安全的(根据文档)。所以可以使用props.computeIfAbsent()
。但我更喜欢这种方式。
另请阅读:Scope of the Java System Properties
我刚刚写了它,并且有可能我忽略了一些会阻止它工作的东西。