java - 保护映射免受 java 中线程的影响

标签 java multithreading collections

我有一种情况,我有一张巨大的 map ,我在其中维护一些数据。 我的应用程序是多线程的。

一个线程可能会尝试从映射中删除条目,而第二个线程可能会尝试复制映射。 以下是描述我的问题的示例代码。

public class CollectionsTest {
    static Map<String, String> map = new HashMap<>();
    public static void main(String [] args) throws InterruptedException {
        for(long i=0;i<1000000; i++){
            map.put("key"+i, "value"+i);
        }
        Thread t1 = new Thread(new Task1());
        Thread t2 = new Thread(new Task2());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
    private static class Task1 implements Runnable {
        @Override
        public void run() {
            System.out.println("Task 1 start");
            Map<String, String> copy = new HashMap<>(map);
            System.out.println(copy.get("key1"));
            System.out.println("Task 1 done");
        }
    }
    private static class Task2 implements Runnable {
        @Override
        public void run() {
            System.out.println("Task 2 start");
            map.remove("key2");
            System.out.println("Task 2 end");
        }
    }
}

以下是输出

Task 1 start
Task 2 start
Task 2 end
Exception in thread "Thread-0" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
    at java.util.HashMap.putMapEntries(HashMap.java:511)
    at java.util.HashMap.<init>(HashMap.java:489)
    at com.alcatel.pma.core.configmgmt.CollectionsTest$Task1.run(CollectionsTest.java:27)
    at java.lang.Thread.run(Thread.java:745)

Process finished with exit code 0

避免这种情况的最佳方法是什么?

最佳答案

在多线程环境中处理数据结构时,基本上有两种选择。

  1. 您选择同步实现,例如 ConcurrentHashMap、CopyOnWriteArray 等。这些数据结构旨在同时使用。实现细节差异很大(写入数据克隆、锁/信号量、监视器(同步关键字),您必须谨慎选择最合适的结构。

  2. 您可以使用锁(ReentrandRead/WriteLock)或 Java 监视器来同步对未同步数据结构的访问。

如果您对并发不太了解,建议选择第一个选项。如果您想学习更多有关 Java 编程的知识,请选择选项二。

关于java - 保护映射免受 java 中线程的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40045542/

相关文章:

multithreading - CUDA computeprof无法与多线程一起使用

java - 我们可以在LinkedHashSet中的固定点插入元素吗?

c# - 在 C# 中使用反射添加到未知类型的集合

java - 如何在 Eclipse 中引用不同的 Java 项目

java - 使用 64 位 java 运行 Netlogo

java - 如何证明 i++ 不是原子的

java - 查询 Google 的目录 API - 错误 : 400 Bad Request

java - 如何在 Servlet 中的 doGet 和 doPost 方法之间传递局部变量?

c++ - 以下 C++ 代码线程安全吗?

c# - C# 应用程序中的 SQL 过滤器和或语句