2009-11-05 35 views
1

即使假设您将构建其他映射的成本排除在putAll()之外,通常(即不是并发),putAll()也不会比使用批次的put()更高效。这是因为putAll()将需要迭代传递的Map元素,并且需要贯穿算法,将每个键值对添加到执行的映射。ConcurrentHashMap和putAll()方法

但是对于一个ConcurrentHashMap,构建一个常规Map然后使用putAll()来更新它是否有意义?或者我应该对put()进行10(或100,或1000)的呼叫?

对于putIfAbsent()的多次呼叫,答案是否会更改?

谢谢!

+0

你甚至使用线程来填充ConcurrentHashMap吗?如果不是,则putAll()或100个连续put()的 – jitter 2009-11-05 02:18:07

+0

之间不会有任何区别是(至少)有一个线程正在写入ConcurrentHashMap,并且多个线程正在读取它。 – Rudiger 2009-11-05 02:25:18

+0

PutAll()就像是一个在CHM中添加多个元素的自动化过程,比一个一个地自己做。 – AKS 2013-08-20 04:14:10

回答

3

Java Collections中的第一个(大部分)线程安全映射是使用Collections.synchronizedMap()同步的HashMap。它一次只允许一次操作。 Java 5添加了ConcurrentHashMap,其工作方式不同。基本上Map分为切片。 A put()操作将只锁定相关切片。它还添加了线程安全基元,如putIfAbsent()

我解释这个的原因是putAll()可能或多或少有效取决于它的实现方式。它可以通过锁定整个地图来工作,这实际上可能比试图获得每个put()上的个人锁定更有效率。或者它可能通过做一堆put()调用,在这种情况下没有太大的区别。

因此,如果它对您的代码有意义,并且您正在进行大量更新,那么我会使用putAll(),除非它是putIfAbsent()

编辑:我刚才检查时,Java 6 ConcurrentHashMap工具putAll()put()操作的循环,因此没有比这样做你自己更好或更坏。

+0

我认为它可能会获得所有更新的一个锁,但我猜不是。我将对ConcurrentHashMap的'put()'进行单独调用,并避免构建另一个Map的成本。 – Rudiger 2009-11-05 02:49:27

+0

查看源代码的好处,但是我认为“没有更好或更差”,因为更清晰的代码更清晰代码^^ – 2009-11-05 02:49:49

+0

有更清晰的代码很好,但使用'putAll()'我必须创建一个新的Map(无论如何都会产生对put()的多次调用)。 – Rudiger 2009-11-05 03:00:24

2

putAll()只是代表put()。如果您还没有建立中间地图,则无需建立中间地图。您可以在源代码中看到这一点,因为代码是公有领域并且由所有人共享,所以您使用的Java实现无关紧要。

请注意,putAll()是不是原子,但只是保证每个人put()是原子。