使用 AtomicReference 的带有参数的单例
Singleton with arguments using AtomicReference
我必须创建一个接受输入参数的单例。基本上我需要根据一些配置在库中创建一个 DBConnector。现在这个配置由消费应用程序传递给库。基于传入的配置,我想创建一个 DBConnector 实例,然后在库中重复使用它。
我想过使用 DI 来处理这个问题,但是当这个库被初始化时我不知道是否真的需要一个 DB 连接,如果不需要的话我不想创建这个 DBConnector。
初始化库后,在调用 getResponse(RequestType rt) 时,我会知道是否需要 DBConnector(基于 RequestType),那是我需要创建实例的时候。
因此下面的代码看起来适合多线程环境?
public class DBConnectorFactory
{
private static volatile DBConnector dBConnector = null;
private static AtomicReference<DBConnector> atomicReference = new AtomicReference<>();
private DBConnectorFactory()
{}
public static DBConnector getDBConnector(DBConfig dBConfig)
{
if(dBConnector == null)
{
if(atomicReference.compareAndSet(null,new DBConnector(dBConfig)))
dBConnector = atomicReference.get();
return atomicReference.get();
}
else
return dBConnector;
}
}
编辑
编写了一个多线程测试,所有线程都获得了相同的实例。但是,只是想确保我不会因为 Java 内存模型
而错过任何边缘情况
照原样,我觉得它符合逻辑。
我觉得有趣的一件事是你使用单例模式,如果你输掉一场比赛并求助于使用第二个 AtomicReference#get()
,它可能会丢弃 DBConnector
的一个实例。单身人士的全部意义不就是确保 ever 只创建一个实例吗?如果这是您的意图,那么您使用的模式不适合这个。您必须同步。
否则,如果您坚持使用无锁初始化并且可能有多个实例化,您应该只使用一个 AtomicReference,如下所示:
private static AtomicReference<DBConnector> instance = new AtomicReference<>();
public static DBConnector getDBConnector(DBConfig dBConfig) {
// First try
DBConnector con = instance.get();
if (con == null) {
con = // ...
if (instance.compareAndSet(null, con)) {
// Successful swap, return our copy
return con;
} else {
// Lost the race, poll again
return instance.get():
}
}
// Already present value
return con;
}
我必须创建一个接受输入参数的单例。基本上我需要根据一些配置在库中创建一个 DBConnector。现在这个配置由消费应用程序传递给库。基于传入的配置,我想创建一个 DBConnector 实例,然后在库中重复使用它。 我想过使用 DI 来处理这个问题,但是当这个库被初始化时我不知道是否真的需要一个 DB 连接,如果不需要的话我不想创建这个 DBConnector。 初始化库后,在调用 getResponse(RequestType rt) 时,我会知道是否需要 DBConnector(基于 RequestType),那是我需要创建实例的时候。 因此下面的代码看起来适合多线程环境?
public class DBConnectorFactory
{
private static volatile DBConnector dBConnector = null;
private static AtomicReference<DBConnector> atomicReference = new AtomicReference<>();
private DBConnectorFactory()
{}
public static DBConnector getDBConnector(DBConfig dBConfig)
{
if(dBConnector == null)
{
if(atomicReference.compareAndSet(null,new DBConnector(dBConfig)))
dBConnector = atomicReference.get();
return atomicReference.get();
}
else
return dBConnector;
}
}
编辑 编写了一个多线程测试,所有线程都获得了相同的实例。但是,只是想确保我不会因为 Java 内存模型
而错过任何边缘情况照原样,我觉得它符合逻辑。
我觉得有趣的一件事是你使用单例模式,如果你输掉一场比赛并求助于使用第二个 AtomicReference#get()
,它可能会丢弃 DBConnector
的一个实例。单身人士的全部意义不就是确保 ever 只创建一个实例吗?如果这是您的意图,那么您使用的模式不适合这个。您必须同步。
否则,如果您坚持使用无锁初始化并且可能有多个实例化,您应该只使用一个 AtomicReference,如下所示:
private static AtomicReference<DBConnector> instance = new AtomicReference<>();
public static DBConnector getDBConnector(DBConfig dBConfig) {
// First try
DBConnector con = instance.get();
if (con == null) {
con = // ...
if (instance.compareAndSet(null, con)) {
// Successful swap, return our copy
return con;
} else {
// Lost the race, poll again
return instance.get():
}
}
// Already present value
return con;
}