【问题标题】:ConcurrentHashMap with ArrayList as value以 ArrayList 为值的 ConcurrentHashMap
【发布时间】:2011-08-20 20:56:13
【问题描述】:

我需要使用 <String, ArrayList<String>> 形式的 HashMap 由几个不同的线程访问。据我了解, ConcurrentHashMap 是首选方法。但是map的值是一个ArrayList会不会有什么问题呢?我是否必须将值定义为同步的 ArrayList 或类似的东西?

【问题讨论】:

    标签: java concurrency arraylist hashmap


    【解决方案1】:

    是的,可能有问题。 ConcurrentHashMap 对 Map 的访问是线程安全的,但提供的 List 需要是线程安全的,如果多个线程可以同时对同一个 List 实例进行操作。

    如果是这样,请使用线程安全列表。

    编辑——现在我想起来了,兔子洞走得更远了。你有你的地图,你有你的列表,你有列表中的对象。任何多线程可以修改的东西都应该是线程安全的。因此,如果许多线程可以修改 Lists 中的 Map、Lists 和 Objects,那么所有这些都应该具有线程安全防护。如果只有 Map 和 List 实例可以并发修改,那么只有它们需要线程安全。如果多个线程可以读取所有内容,但不能修改,那么您不需要任何线程安全(我想,如果这是错误的,有人会纠正我)

    【讨论】:

    • 我明白了……那么我该如何使用线程安全列表呢?我的意思是,如何初始化 ConcurrentHashMap?我不能写新的 ConcurrentHashMap>()...
    • 好吧,假设对同一个 List 的访问非常少见,那么只要在从 HashMap 获取它之后在列表上同步(synchronize(list) {})就可以了。否则 Collections.synchronizedList() 仍然返回一个普通列表,因此您不必更改哈希映射的签名 - 只需确保仅将同步列表添加到映射。
    • @Moshe:为了让 Voo 的评论更清楚:使用 <String, List<String>> 作为地图的类型参数,而不是 <String, someSpecialListType<String>>。然后你可以放入任何你想要的列表——通常你不需要知道哪个实现。
    【解决方案2】:

    ConcurrentHashMap 保证其变异方法的原子性,例如putIfAbsent、computeIfAbsent、computeIfPresent,所以如果所有的修改都通过这些方法完成,就不会出现问题。

    但同时,多个线程可以读取同一个映射条目(允许并发读取)。因此多个线程可以访问和修改不安全的集合(映射值)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 1970-01-01
      相关资源
      最近更新 更多