Java 并发:当并发线程仅删除元素时,HashMap 与 ConcurrentHashMap

我有一个主线程,它创建一个 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);

}


叮当猫咪
浏览 220回答 3
3回答

拉丁的传说

如果您这样做的原因是跟踪线程完成情况,为什么不使用 CountdownLatch?不确定 HashMap 是否只能在删除时出现并发问题,我建议仅当您的代码不会因任何可能的问题而中断时才使用它,或者使用 ConcurrentHashMap。

慕田峪7331174

javadoc说HashMap:请注意,此实现不是同步的。如果多个线程同时访问哈希图,并且至少有一个线程在结构上修改了该图,则必须进行外部同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常是通过在自然封装映射的某个对象上进行同步来完成的。上面提到,删除是一个结构性的改变,必须使用同步。再者,在removeNode()Hashmap的方法中(方法调用的remove()),modCount变量是递增的,它负责ConcurrentModificationException. 因此,如果在没有同步的情况下删除元素,您可能会遇到此异常。因此您必须使用ConcurrentHashMap.

眼眸繁星

您询问了HashMap和之间的差异ConcurrentHashMap,但还需要考虑一个额外的数据结构:Hashtable。每一个都存在差异和权衡。您需要评估哪一个最适合您的预期用途。HashMap是不同步的,因此如果多个线程可以读取或写入它,您的结果将是不可预测的。HashMap还允许 null 作为键或值。Hashtable是同步的,不支持空键或值。来自哈希表 Javadoc:哈希表是同步的。如果不需要线程安全的实现,建议使用HashMap代替Hashtable。如果需要线程安全的高并发实现,那么建议使用ConcurrentHashMap代替Hashtable。ConcurrentHashMap是线程安全的,不允许使用 null 作为键或值。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java