gpt4 book ai didi

java - 单例对象工厂 : is this code thread-safe?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:22:50 24 4
gpt4 key购买 nike

我有一个用于许多单例实现的通用接口(interface)。接口(interface)定义了可以抛出检查异常的初始化方法。

我需要一个工厂来按需返回缓存的单例实现,想知道以下方法是否线程安全?

UPDATE1:请不要建议任何第三部分库,因为由于可能的许可问题,这将需要获得法律许可:-)

更新 2:此代码可能会在 EJB 环境中使用,因此最好不要产生额外的线程或使用类似的东西。

interface Singleton
{
void init() throws SingletonException;
}

public class SingletonFactory
{
private static ConcurrentMap<String, AtomicReference<? extends Singleton>> CACHE =
new ConcurrentHashMap<String, AtomicReference<? extends Singleton>>();

public static <T extends Singleton> T getSingletonInstance(Class<T> clazz)
throws SingletonException
{
String key = clazz.getName();
if (CACHE.containsKey(key))
{
return readEventually(key);
}

AtomicReference<T> ref = new AtomicReference<T>(null);
if (CACHE.putIfAbsent(key, ref) == null)
{
try
{
T instance = clazz.newInstance();
instance.init();
ref.set(instance); // ----- (1) -----
return instance;
}
catch (Exception e)
{
throw new SingletonException(e);
}
}

return readEventually(key);
}

@SuppressWarnings("unchecked")
private static <T extends Singleton> T readEventually(String key)
{
T instance = null;
AtomicReference<T> ref = (AtomicReference<T>) CACHE.get(key);
do
{
instance = ref.get(); // ----- (2) -----
}
while (instance == null);
return instance;
}
}

我不完全确定第 (1) 和 (2) 行。我知道引用的对象在 AtomicReference 中声明为 volatile 字段,因此在第 (1) 行所做的更改应该在第 (2) 行立即可见 - 但仍有一些疑问......

除此之外 - 我认为 ConcurrentHashMap 的使用解决了将新 key 放入缓存的原子性问题。

你们看到这种方法有什么问题吗?谢谢!

P.S.:我知道静态持有者类惯用语 - 由于 ExceptionInInitializerError(在单例实例化过程中抛出的任何异常都被包装到其中),我没有使用它,并且随后的 NoClassDefFoundError 这不是我想要捕捉的。相反,我想通过捕获并优雅地处理它来利用专用检查异常的优势,而不是解析 EIIR 或 NCDFE 的堆栈跟踪。

最佳答案

您已经做了很多工作来避免同步,我认为这样做的原因是出于性能考虑。您是否测试过与同步解决方案相比,这是否真的提高了性能?

我问的原因是并发类往往比非并发类慢,更不用说原子引用的附加重定向级别了。根据您的线程争用,简单的同步解决方案实际上可能更快(并且更容易验证正确性)。

此外,我认为在调用 instance.init() 期间抛出 SingletonException 时,您可能会以无限循环结束。原因是在 readEventually 中等待的并发线程永远不会找到它的实例(因为在另一个线程初始化实例时抛出异常)。也许这对您的情况来说是正确的行为,或者您可能想为实例设置一些特殊值以触发将异常抛出到等待线程。

关于java - 单例对象工厂 : is this code thread-safe?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8331413/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com