我有一个类 A,它有一个 HashMap 作为公共(public)字段:
public static final HashMap<String, String> map = new HashMap<String, String>();
在类 B(它是多线程的,实现 Runnable)中,我做了一些 put。
现在,在 C 课上,我正在尝试读取 map 。但对 map 的改变并没有反射(reflect)在C类中。
我没有在任何地方存储任何引用,但我通过类名访问 map 。
A.map.put("hi", "hello"); //in thread B
A.map.get("hi"); //in thread C
我确信我在调用 put() 之后调用了 get() ..
我以为并发可能有问题,我把HashMap改成了Hashtable,但还是一样。
我用尽可能少的代码复制了这个问题
public class A {
public static final HashMap<String, String> map = new HashMap<String, String>();
public static void main(String[] args){
while(true);
}
}
public class B {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(true){
String s = sc.nextLine();
A.map.put(s, "true");
System.out.println(A.map.size());
}
}
}
public class C {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(true){
sc.nextLine();
System.out.println(A.map.size());
}
}
}
我可以看到 B 类中的打印尺寸增加,但 C 类中的尺寸始终为零..
我在这里遗漏了什么吗?
最佳答案
当从不同线程执行操作时,您希望在同一对象上强制同步。
目前,您没有进行任何同步,因此它不起作用。
因此你有两个选择:
将其包装到同步映射中,其中
Collections.synchronizedMap(new HashMap<>());
。这会强制所有操作同步,即使它们来自同一线程。在 map 上执行操作时使用相同的锁。我不建议使用后一种方法,除非您要在单个线程上连续执行大量操作,而其他线程不需要知道这些操作。
根据 @Ziker 的建议,第三个选项是使用 ConcurrentHashMap
,它提供了与将其包装在 Collections.synchronizedMap
中相同的线程安全性。 ,但成本不同,这意味着这确实应该是您的首选。
关于java - 类之间的 HashMap 不一致 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23199206/