【发布时间】:2019-09-25 03:23:27
【问题描述】:
我有一个创建 HashMap 的主线程,向其中添加多个可运行对象,然后启动每个可运行对象(将 HashMap 传递给每个对象)。可运行对象在即将完成处理之前从映射中移除其对象。
我想知道在这种情况下是否有任何理由使用 ConcurrentHashMap(而不是 HashMap) - 可运行对象在地图上执行的唯一操作是将自己从地图中移除。在这种情况下是否存在需要使用 ConcurrentHashMap 的并发性考虑?
主线程
private final Map<Integer, Consumer> runnableMap = new HashMap<>();
Runnable runnable;
for (int i = 1; i <= NUM_RUNNABLES; i++) {
runnable = new Consumer(i, runnableMap);
runnableMap.put(i, runnable);
executionContext.execute(runnable);
}
消费者实现 Runnable
private final Integer consumerNumber;
private final Map<Integer, Consumer> runnableMap;
public Consumer(int consumerNumber, final Map<Integer, Consumer> runnableMap){
this.consumerNumber = consumerNumber;
this.runnableMap = runnableMap;
}
public void run() {
:::
// business logic
:::
// Below remove is the only operation this thread executes on the map
runnableMap.remove(consumerNumber);
}
【问题讨论】:
-
从地图中删除项目的代码不是
HashMap中的原子操作。并且还会出现可见性问题。您必须使用线程安全的ConcurrentHashMap。 -
Kartik - 谢谢!但由于可运行文件不读取或更新地图中的任何元素,因此我不清楚在这种情况下可能出现的可见性问题。主线程是否能够在地图上看到已经完成执行的可运行元素?
-
为什么?为什么不直接运行
Queue或Runnables?为什么不将该队列提供给ExecutorService?地图有什么用? -
passing a copy of the HashMap to each这不是副本,因为它看起来像是对同一个对象的引用。 -
michalk - 你是对的。它是相同的HashMap。我已经更正了。
标签: java concurrency concurrenthashmap