ane*_*est 6 java singleton factory atomic thread-safety
我有一个用于许多单例实现的通用接口.接口定义了可以抛出检查异常的初始化方法.
我需要一个工厂,它将按需返回缓存的单例实现,并想知道以下方法是否是线程安全的?
更新1:请不要建议任何第3部分图书馆,因为这可能需要获得法律许可,因为可能的许可问题:-)
更新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;
}
}
Run Code Online (Sandbox Code Playgroud)
我不完全确定第(1)和(2)行.我知道引用的对象被声明为volatile字段AtomicReference,因此第(1)行所做的更改应该在第(2)行立即可见 - 但仍有一些疑问......
除此之外 - 我认为使用ConcurrentHashMap地址将新密钥放入缓存的原子性.
你们看到这种方法有什么顾虑吗?谢谢!
PS:我知道静态持有者类习惯用法 - 我不使用它(由于ExceptionInInitializerError在单例实例化中抛出的任何异常被包装)以及随后NoClassDefFoundError哪些不是我想要捕获的东西.相反,我想通过捕获它并优雅地处理它来利用专用检查异常的优势,而不是解析EIIR或NCDFE的堆栈跟踪.
考虑使用 Guava 的CacheBuilder. 例如:
private static Cache<Class<? extends Singleton>, Singleton> singletons = CacheBuilder.newBuilder()
.build(
new CacheLoader<Class<? extends Singleton>, Singleton>() {
public Singleton load(Class<? extends Singleton> key) throws SingletonException {
try {
Singleton singleton = key.newInstance();
singleton.init();
return singleton;
}
catch (SingletonException se) {
throw se;
}
catch (Exception e) {
throw new SingletonException(e);
}
}
});
public static <T extends Singleton> T getSingletonInstance(Class<T> clazz) {
return (T)singletons.get(clazz);
}
Run Code Online (Sandbox Code Playgroud)
注意:此示例未经测试和编译。
Guava 的底层Cache实现将为您处理所有缓存和并发逻辑。
| 归档时间: |
|
| 查看次数: |
1052 次 |
| 最近记录: |