当前位置: 首页 > 知识库问答 >
问题:

单例类中多个线程使用同一对象的影响

唐信瑞
2023-03-14

我正在设计一个模块,可以支持不同的数据源。我的模块获取用户的公司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”是一个接口,而communicator映射将返回适当的实例。这是同一个单例类中的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());
}
Communicator comm;
if (type = "AD") comm = new ADCommunicator();
if (type = "DB2") comm = new DB2Communicator();
if (type = "MYSQL") comm = new MYSQLCommunicator();

共有1个答案

沙星波
2023-03-14

我似乎无法避免在hashmap中使用相同的实例

你可以用一个开关来代替一堆如果。

type更改为Java5+中的枚举,然后就可以对其进行切换。为了类型安全,我推荐一般的枚举。

// 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;
}

Java8可以直接切换字符串

// type is-a String
switch(type) {
    case "AD": return new ADCommunicator();
    case "DB2": return new DB2Communicator();
    case "MYSQL": return new MYSQLCommunicator();
    default: return null;
}
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();
// 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;
}
 类似资料:
  • 我已经面临这个问题很多天了,请帮我解决。我正在使用线程同步实现生产者-消费者示例。我在这个传统节目中做了一些调整。我没有只使用一个队列对象,而是使用了两个队列对象。但程序不起作用。。(PS-我知道我可以通过只使用队列的一个对象来让这个程序工作,但如果我想使用两个队列对象呢??) 类队列{ } 类生产者实现Runnable{ } 类消费者实现可运行{ } 公共类测试队列{ }

  • 现在我的问题是:关键字对这种情况有用吗?

  • 如果我没有错的话,Thread-1和thread-3正在进入synchronized方法,因为它有两个不同的目标对象。但是为什么线程2进入同步块呢? 请帮助我理解这一点。提前谢了。

  • 我正在学习多线程的基础知识,并且正在编写一个程序来理解使用两种创建线程的方法之间的区别。 我已经读到,使用Runnable允许多个线程共享同一个对象,并希望在扩展线程时尝试类似的事情。因此,在创建了Demo2的新对象之后,我将引用传递给了线程构造函数(类似于我们在Runnable中所做的)。 当objT1,tT1,tT2将总和的值增加到3时,我达到了我想要达到的目标。但是在打印当前线程的名称时,它

  • 我正在学习多线程的基础知识,并且正在编写一个程序来理解使用两种创建线程的方法之间的区别。 我已经读到,使用Runnable允许多个线程共享同一个对象,并希望在扩展线程时尝试类似的事情。因此,在创建了Demo2的新对象之后,我将引用传递给了线程构造函数(类似于我们在Runnable中所做的)。 当objT1,tT1,tT2将总和的值增加到3时,我达到了我想要达到的目标。但是在打印当前线程的名称时,它

  • 问题内容: 我是Hibernate的新手,必须支持使用Hibernate的现有应用程序。这是一个纯报表应用程序-无需插入/更新/删除-仅选择 我可以看到在同一类的多个字段中使用了@Id注释的现有POJO对象 我的理解是,对于复合主键-您需要使用@Embeddable和@EmbeddedId 但是,这没有在我的课程中定义,奇怪的是代码可以编译并正常运行 这是我的代码的示例: 在pojo中还有更多字段