Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java并发性:当并发线程只删除元素时,HashMap与ConcurrentHashMap_Java_Concurrency_Concurrenthashmap - Fatal编程技术网

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

Java并发性:当并发线程只删除元素时,HashMap与ConcurrentHashMap,java,concurrency,concurrenthashmap,Java,Concurrency,Concurrenthashmap,我有一个主线程,它创建一个HashMap,向其中添加多个可运行对象,然后启动每个可运行对象(将HashMap传递给每个对象)。runnable在即将完成处理之前从映射中删除其对象 我想知道在这种情况下是否有任何理由使用ConcurrentHashMap(而不是HashMap)——可运行程序对映射执行的唯一操作是将自己从映射中移除。在这种情况下,是否有需要使用ConcurrentHashMap的并发性考虑 主线 private final Map runnableMap=new HashMap()

我有一个主线程,它创建一个HashMap,向其中添加多个可运行对象,然后启动每个可运行对象(将HashMap传递给每个对象)。runnable在即将完成处理之前从映射中删除其对象

我想知道在这种情况下是否有任何理由使用ConcurrentHashMap(而不是HashMap)——可运行程序对映射执行的唯一操作是将自己从映射中移除。在这种情况下,是否有需要使用ConcurrentHashMap的并发性考虑

主线
private final Map runnableMap=new HashMap();
可运行的可运行的;

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

您询问了
HashMap
ConcurrentHashMap
,但还有一个额外的数据结构需要考虑:
Hashtable
。每个数据结构都有差异和权衡。您需要评估哪个最适合您的预期用途

  • HashMap
    是不同步的,因此如果有多个线程可以读取或写入它,那么结果将是不可预测的。
    HashMap
    还允许null作为键或值

  • 哈希表
    已同步,不支持空键或值。发件人:

    哈希表是同步的。如果不需要线程安全的实现,建议使用HashMap代替Hashtable。如果需要线程安全的高并发实现,建议使用ConcurrentHashMap代替Hashtable


  • ConcurrentHashMap
    是线程安全的,不允许将null用作键或值

报告说:

请注意,此实现不是 已同步。

如果多个线程访问哈希映射 同时,并且至少有一个线程修改映射 在结构上,它必须在外部同步 结构修改是添加或删除结构修改的任何操作 一个或多个映射;仅更改与键关联的值 实例已包含的不是结构类型 这通常通过在上同步来完成 自然封装贴图的某个对象

如上所述,删除是一种结构更改,必须使用同步

此外,在Hashmap方法(由
remove()
方法调用)中,
modCount
变量是递增的,它负责
ConcurrentModificationException
。因此,如果在不同步的情况下删除元素,可能会出现此异常


因此,您必须使用
ConcurrentHashMap

从映射中删除项目的代码在
HashMap
中不是一个原子操作。而且还会出现可见性问题。您必须使用线程安全的
ConcurrentHashMap
。Kartik-谢谢!但是由于runnables不读取或更新映射中的任何元素,我不清楚关于在本例中可能出现的可见性问题。主线程是否能够在映射上看到已完成执行的可运行元素?为什么?为什么不运行一个
可运行的
队列
?为什么不将该队列提供给
ExecutorService
?映射用于什么?
传递Ha副本shMap to each
这不是一个副本,因为它看起来像是对同一个对象的引用。michalk-你说得对。它是同一个哈希映射。我已经做了更正。谢谢Martin!Runnable实际上是长时间运行的侦听器,只有在出现异常时才会终止。在任何给定时刻,我都希望能够确定活动r的数量主线程定期轮询映射以补偿任何“死”的可运行项(通过添加新的可运行项).谢谢Kaan!鉴于runnable只从映射中删除他们自己的实例,并且不读取/更新任何元素,在这种情况下,是否有任何线程安全问题需要担心?您能否帮助我了解我的主线程是否会立即看到删除,而不是使用HashMap实现的每个runnable中的情况?可能是这样的在您的案例中可以使用非并发结构,但我要提醒您仔细考虑。如果您最终推断不需要并发保护,但您错了,您可能会遇到非常混乱的行为。出于速度/性能考虑,有理由避免不必要的并发保护,但是一般来说,我首先从代码是可证明正确的,然后只考虑优化您的数据结构(也许).
ConcurrentHashMap
不是同步的,但它是线程安全的。re:您必须使用ConcurrentHashMap–OP可以使用
ConcurrentHashMap
Hashtable
获得正确的并发行为。只有
ConcurrentHashMap
才能工作并不是绝对的。@kaan首先,OP在HashMap和ConcurrentHashM之间询问ap而不是Hashtable。其次,Hashtable被认为是过时的。ConcurrentHashMap性能优于Hashtable,因为它不需要锁定。同意,OP询问了这两个问题,但为了让大家知道还有第三个选项。Hashtable从JDK 1.0开始就存在,但它仍然可用,并且没有被弃用。说OP“必须使用”X是不正确的。@kaan为什么你不提到BlockingQueue、信号量和锁以供一般注意?它们都可以在这种情况下使用。与“必须使用”相比,我的意思是“与HashMap相比”。这仍然不是一个否决投票的好理由。Kartik-非常感谢!我找到了Javadoc参考
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);
}
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);
}