HashTable是一个线程安全的集合,但是是否使用ArrayList初始化它(因为它不是线程安全的),因为它的值危及整个线程安全方面?
Hashtable <Employee, ArrayList<Car>> carDealership = new Hashtable<>();
进一步,我计划将
ArrayLists
的每个 Action 包装在synchronized
块中,以防止在使用任何方法进行操作时出现任何竞争条件。但是我还没有在HashTable中将ArrayLists声明为同步列表,这是通过以下代码实现的
Collections.synchronizedList(new ArrayList<>())
显然,当我将ArrayLists添加到HashTable时,就会发生这种情况。
如何确定
ArrayLists
中的HashTable
是线程安全的?是否足以将线程安全的
ArrayList
传递到put()
的hashTable
方法,我很好吗? (甚至不必担心HashTable
的构造函数吗?)因此,如果我传递线程安全/不安全参数,则HashTable的put()
方法甚至无法识别?注意:线程安全是必需的。否则,我将不会选择此实现。
最佳答案
确保 Hashtable
或 ConcurrentHashMap
中的值是线程安全的唯一方法是将其包装起来,以防止任何人添加您无法控制的内容。切勿将Map
本身或其中的任何List
暴露给代码的其他部分。提供方法以获取快照副本(如果需要),提供方法以将值添加到列表中,但是请确保包装 map 的类是将创建所有可以添加到列表中的列表的类。映射中“ Activity ”列表的迭代将需要外部同步(如in the JavaDocs of synchronizedList
所提及)。Hashtable
和ConcurrentHashMap
都是线程安全的,因为并发操作不会使它们处于无效状态。这意味着如果您使用相同的键从两个线程调用put
,则其中一个将返回该值,另一个将作为“旧”值插入。但是,当然,如果没有一些外部同步,您将无法事先知道哪个会是第一个,哪个会是第二个。
不过,实现方式却大不相同:Hashtable
和Map
返回的同步Collections.synchronizedMap(new HashMap());
类似,因为它们基本上向大多数方法添加了synchronized
修饰符。如果您有很多线程(大多数情况下都是锁的争夺者)读取的最多,但偶尔会修改映射,则效率可能会很低。 ConcurrentHashMap
提供了更细粒度的锁定:
Retrieval operations (including get) generally do not block
根据您的使用情况,它可以产生明显更好的性能。我还提供了具有功能强大的搜索和批量修改操作的更丰富的API。
关于java - 如何使用安全线程对象作为值初始化hashTable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49674362/