java - 类之间的 HashMap 不一致 - Java

标签 java concurrency hashmap

我有一个类 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 类中的尺寸始终为零..

我在这里遗漏了什么吗?

最佳答案

当从不同线程执行操作时,您希望在同一对象上强制同步

目前,您没有进行任何同步,因此它不起作用。

因此你有两个选择:

  1. 将其包装到同步映射中,其中 Collections.synchronizedMap(new HashMap<>()); 。这会强制所有操作同步,即使它们来自同一线程。

  2. 在 map 上执行操作时使用相同的锁。我不建议使用后一种方法,除非您要在单个线程上连续执行大量操作,而其他线程不需要知道这些操作。

根据 @Ziker 的建议,第三个选项是使用 ConcurrentHashMap ,它提供了与将其包装在 Collections.synchronizedMap 中相同的线程安全性。 ,但成本不同,这意味着这确实应该是您的首选。

关于java - 类之间的 HashMap 不一致 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23199206/

相关文章:

java - 给定一个具有字符串类型值的映射,这些值都是用逗号分隔的数字,是否可以将每个值转换为 double 值?

java - Android 资源中的图像导致内存泄漏

java - 复合键的 JPQL 异常

file - 对文件的独占\同步访问(排队)

基于可用 FREE cpu 的 Java 并发性

android - 如何在Android中使用HashMap从Firebase中的子级的子级获取数据?

java - 从 Java 执行查询时哪种方式更好

java - getKeyStroke(char) 与 getKeyStroke(char, int) - 我不明白区别

c++ - 并发写入 std::vector 到不同的索引会导致崩溃?

java - HashMap.toString() 方法的线程安全