Java:在单个线程中修改对象,读入多个线程

时间:2017-09-19 23:11:52

标签: java android multithreading concurrency thread-safety

当一个对象(例如HashMap或ArrayList或某些POJO)总是被单个(相同的)线程修改但可以被多个线程访问时,实现线程安全的通用方法是什么?

HashMap对我来说是最感兴趣的,但我需要一种通用的方法。

是否足以让它变得不稳定?

感谢。

2 个答案:

答案 0 :(得分:1)

也许你应该看看ConcurrentHashMap。

  

公共类ConcurrentHashMap

     

扩展AbstractMap

     

实现ConcurrentMap,Serializable

     

支持检索的完全并发和更新的高预期并发性的哈希表。该类遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法相对应的方法版本。但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。在依赖于线程安全但不依赖于其同步细节的程序中,此类可与Hashtable完全互操作。

     

检索操作(包括get)一般不会阻塞,因此可能与更新操作重叠(包括put和remove)。检索反映了最近完成的更新操作的结果。 (更正式地说,给定密钥的更新操作承担与报告更新值的该密钥的任何(非空)检索之前发生的关系。)对于诸如putAll和clear之类的聚合操作,并发检索可能反映插入或删除只有一些条目。类似地,Iterators,Spliterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。它们不会抛出ConcurrentModificationException。但是,迭代器设计为一次只能由一个线程使用。请记住,聚合状态方法的结果(包括size,isEmpty和containsValue)通常仅在映射未在其他线程中进行并发更新时才有用。否则,这些方法的结果反映了可能足以用于监视或估计目的的瞬态,但不适用于程序控制。

更多信息: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html

它的行为与programicalaly完全类似于经典的hashmap。

答案 1 :(得分:1)

通用方法不易实现,需要您付出很多努力,但事情仍然会出错(因为它太难了)。所以,你最好的选择是Gomoku7建议的ConcurrentHashMap。

通用方法需要基于锁的实现。您必须在更新之前锁定对象并释放后锁定。 Java中有不同的types of locks。所以,选择适合您需要的锁具。有一些提示:

  1. Final是你的朋友,除非有必要,否则不要改变对象,尽可能使对象final
  2. 避免创建临时变量
  3. 尽可能使用ExecutorsFork/Join