Java 具有多线程和实例共享的泛型

Java 具有多线程和实例共享的泛型,java,generics,garbage-collection,Java,Generics,Garbage Collection,我有一个泛型类,可以这样画 public class Shared<T extends EntityBase> { private HashMap<String, Class<? extends Executor<T>>> classes; private HashMap<String, ? super Executor<T>> instances; private List<Entity&g

我有一个泛型类,可以这样画

public class Shared<T extends EntityBase> {

    private HashMap<String, Class<? extends Executor<T>>> classes;
    private HashMap<String, ? super Executor<T>> instances;
    private List<Entity> entities;
    private Compiler compiler;

   // Constructor and getters

    public void put(Entity entity, Source source) {
        Class<?> cls = compiler.load(source);
        put(entity, (Class<? extends Executor<T>>) cls );

    }

    private void put(Entity entity, Class<? extends Executor<T>> cls) throws IllegalAccessException, InstantiationException {
        classes.put(entity.getId(), cls);
        instances.put(entity.getId(), cls.newInstance());
        entities.add(entity);
    }
}
公共类共享{
私有HashMap cls=compiler.load(源代码);

put(entity)(Class泛型实际上只是编译器想象的一部分;在运行时这一切都消失了。因此,本例中的泛型与您所看到的完全无关

粘贴的代码无法产生您看到的效果(贴图先更改,然后恢复)。但是,更一般地说,如果您从不同线程调用“put”,则此代码将被破坏。没有防止同步访问的保护措施。当您从不同线程同时更新映射时,映射规范特别指出任何情况都可能发生(从这个意义上说,仅仅重置为空的映射在技术上是“根据规范”的,因为您没有正确处理线程问题,所以任何事情都是允许的)

简单的解决方法是将第二个put方法标记为“synchronized”


另一种策略是使用
java.util.concurrent
包中的列表和映射。但是,再多的使用都不会让您拥有
实例
实体
保证彼此同步。只有
同步
才能做到这一点。

e标记为
synchronized
,我将
HashMaps
替换为
ConcurrentHashMaps
。另一个变化是
ConcurrentHashMaps
键现在都是
实体
实例,而不是
字符串
实例。现在这个
共享
实例没有
松动在两个
ConcurrentHashMaps
中都取消它的
对象
。不确定它是否以某种奇怪的方式与
字符串池
相关。感谢您的关注though@JorgeLav这已经得到了回答。您的原始代码被破坏了,因为它不是线程安全的。它与泛型无关,与garba无关ge集合,没有字符串池。只有多线程。