我有一个情况,我有一个巨大的地图,我维护一些数据。 我的应用程序是多线程的。
一个线程可能会尝试从地图中删除条目,第二个线程可能会尝试复制地图。 以下是描述我的问题的示例代码。
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
避免这种情况的最佳方法是什么?
答案 0 :(得分:2)
在多线程环境中处理数据结构时,基本上有两种选择。
您选择ConcurrentHashMap,CopyOnWriteArray等同步实现。这些数据结构应同时使用。实现细节差别很大(写入时的数据克隆,锁定/信号量,监视器(synchronized关键字),您必须谨慎选择哪种结构最合适。
使用锁(ReentrandRead / WriteLock)或Java监视器同步对非同步数据结构的访问。
如果您对并发性知之甚少,建议选择第一个选项。如果您想学习很多关于Java编程的知识,请选择选项二。