如何用safe-thread对象作为值初始化hashTable?

时间:2018-04-05 14:03:59

标签: java multithreading arraylist thread-safety hashtable

HashTable是一个线程安全的集合,但是使用ArrayList(它不是线程安全的)初始化它,因为值会危及整个线程安全方面吗?

 Hashtable <Employee, ArrayList<Car>> carDealership = new Hashtable<>();

此外,我计划将ArrayLists中的synchronized的每个操作都包含在 Collections.synchronizedList(new ArrayList<>()) 块中,以防止在使用任何方法操作时出现任何竞争条件。

然而,我还没有将HashTable中的ArrayLists声明为同步列表,这是通过以下代码实现的

ArrayLists

当我将ArrayLists显然添加到HashTable时会发生这种情况。

如何确保HashTable中的ArrayList是线程安全的?

是否足以将线程安全的put()传递给hashTable的{​​{1}}方法并且我很高兴?(甚至不担心HashTable的构造函数?)因此,HashTable的put()方法甚至无法识别我是否传递了线程安全/不安全的参数?

注意:线程安全是必需的。否则我不会选择这种实施方式。

2 个答案:

答案 0 :(得分:2)

确保HashtableConcurrentHashMap中的值是线程安全的唯一方法是将其包装起来,以防止任何人添加您无法控制的内容。切勿将Map本身或其中包含的任何List公开给代码的其他部分。如果需要,提供获取快照副本的方法,提供向列表添加值的方法,但要确保包装地图的类是创建可以添加到其中的所有列表的类。对地图中“实时”列表的迭代将需要外部同步(如in the JavaDocs of synchronizedList所述)。

HashtableConcurrentHashMap都是线程安全的,因为并发操作不会使它们处于无效状态。这意味着例如如果从具有相同键的两个线程调用put,则其中一个将返回另一个插入的值作为“旧”值。但是当然你不知道哪一个是第一个,哪个将提前第二个没有一些外部同步。

但是实现完全不同:HashtableMap返回的同步Collections.synchronizedMap(new HashMap());类似,因为它们基本上为大多数方法添加了synchronized修饰符。如果您有大量读取的线程(即锁的高争用),但只是偶尔修改映射,这可能效率低下。 ConcurrentHashMap提供了更细粒度的锁定:

  

检索操作(包括get)一般不会阻塞

根据您的使用情况,可以产生明显更好的性能。我还提供了更丰富的API,具有强大的搜索和批量修改操作。

答案 1 :(得分:0)

是的,在这种情况下使用ArrayList不是线程安全的。您始终可以从表中获取对象并对其进行操作。

CopyOnWriteArrayList是一个很好的替代品。

但是,当一个线程占用(保存在变量中)集合,另一个线程替换另一个线程时,你仍然会遇到这种情况。
如果您不打算替换表中的列表,那么这不是问题。