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