gpt4 book ai didi

java - 多个线程在单例类中使用相同对象的影响

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:09:32 24 4
gpt4 key购买 nike

我正在设计一个可以支持不同数据源的模块。我的模块获取用户的公司 ID 作为输入,我必须根据公司 ID 调用适当的类。我正在尝试合并一些好的设计并尽可能避免条件语句。

我有一个使用此方法的 FetchDataSource 单例类。

public class FetchDataSourceSingleton {

private static Map<String, Communicator> communicatorMap;
public static Communicator getCommunicatorInstance(String dataSourceType) {

if (communicatorMap == null || communicatorMap.isEmpty())
populateCommunicatorMap();

if (communicatorMap.containsKey(dataSourceType))
return communicatorMap.get(dataSourceType);
return null;
}
.... other methods including populateCommunicatorMap()
}

“Communicator”是一个接口(interface),communicator map 会返回合适的实例。这是同一个单例类中的 populateCommunicatorMap() 方法。

    private static void populateCommunicatorMap() {

communicatorMap = new HashMap<String, Communicator>();
communicatorMap.put("AD", new ADCommunicator());
communicatorMap.put("DB2", new DB2Communicator());
communicatorMap.put("MYSQL", new MYSQLCommunicator());
}

ADCommunicator、DB2Communicator 和 MYSQLCommunicator 将实现 Communicator 接口(interface)。

代码似乎在我的测试稿中有效。我唯一担心的是 HashMap 将为所有相同类型的通信请求返回相同的对象。如果我想避免条件语句,我似乎无法避免在 hashmap 中使用相同的实例。否则我可以像这样调用而不是散列图。

Communicator comm;
if (type = "AD") comm = new ADCommunicator();
if (type = "DB2") comm = new DB2Communicator();
if (type = "MYSQL") comm = new MYSQLCommunicator();

我通过使用散列图根据类型返回实例来避免这种情况。但是我无法避免获得相同实例的单例问题。

在需要同时支持数十万个通信请求的多线程环境中,考虑到我需要在每个 Communicator 类中同步大量代码,这可能是个问题。有没有一种方法可以避免同步并使其线程安全而不影响性能?

最佳答案

I can't seem to avoid having the same instance in the hashmap

您可以使用一个开关而不是一堆 ifs。

切换枚举(Java 5)

type 更改为 Java 5+ 中的枚举,然后您可以打开它。为了类型安全,我一般建议使用枚举。

// type is-a enum Communicator.TYPE
switch(type) {
case AD: return new ADCommunicator();
case DB2: return new DB2Communicator();
case MYSQL: return new MYSQLCommunicator();
default: return null;
}

切换字符串(Java 8)

Java 8 可以直接切换字符串。

// type is-a String
switch(type) {
case "AD": return new ADCommunicator();
case "DB2": return new DB2Communicator();
case "MYSQL": return new MYSQLCommunicator();
default: return null;
}

切换枚举将与 map 一样快,如果不是更快的话。打开字符串将与 map 一样快。

工厂 map (工厂的工厂)

或者有一张工厂 map :

private final static Map<String, Factory<? extends Communicator>> map;
static {
map.put("AD", ADCommunicatorFactory.getInstance());
//...
map.put(null, NullFactory<Communicator>.getInstance());
} // populated on class-load. Eliminates race from lazy init

// on get
return map.get(type).make();

类映射(反射)

或者使用反射 API 来创建实例,但是使用条件可能会更好。

// on init
Map<String, Class<? extends Communicator>> map = new HashMap<>();
map.put("AD", ADCommunicator.class);

// on get
try {
return (Communicator) map.get(type).newInstance();
} catch(InstantiationException | IllegalAccessException | NullPointerException e) {
return null;
}

附言这听起来像是过早的优化。我怀疑确定使用哪个 Communicator 会成为您系统中的瓶颈。

关于java - 多个线程在单例类中使用相同对象的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47756329/

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