为什么Scala ConcurrentMap.putIfAbsent总是试图放?

时间:2017-12-03 00:40:47

标签: java scala java.util.concurrent concurrenthashmap

文档中的ConcurrentMap部分声明:

  

m putIfAbsent(k,v)添加键/值绑定k - > v除非k已经存在   以m

定义

但实际上,我发现putIfAbsent总是试图插入v。解决这个问题的方法是使用getOrElseUpdate,但这真的是一个错误,还是我错过了什么?

我的代码如下:

val instanceMap: ConcurrentMap[Address, (MongodExecutable, MongodProcess)] =
    (new JavaConcurrentMap[Address, (MongodExecutable, MongodProcess)]()).asScala

def start(host: String = DefaultAddress.host, port: Int = DefaultAddress.port): MongodProcess = {
  val addr = Address(host, port)
  instanceMap.putIfAbsent(addr, { // this block is ALWAYS executed
    val mongodExecutable = starter.prepare(mongodConfig(host, port))
    val mongod = mongodExecutable.start()
    logProcessInfo(mongod)

    (mongodExecutable, mongod)
  })

  instanceMap(addr)
    ._2
}

1 个答案:

答案 0 :(得分:4)

putIfAbsent会评估k, v的值,因为value不是函数/ lambda。

以下示例

原始并发地图

scala> import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap

scala> new ConcurrentHashMap[String, String]()
res0: java.util.concurrent.ConcurrentHashMap[String,String] = {}

插入key1 - 成功插入返回null

scala> res0.putIfAbsent("127.0.0.1", "mongod-process1")
res1: String = null

scala> res0
res2: java.util.concurrent.ConcurrentHashMap[String,String] = {127.0.0.1=mongod-process1}

插入key2 - 成功插入返回null

scala> res0.putIfAbsent("127.0.0.2", "mongod-process2")
res3: String = null

scala> res0
res4: java.util.concurrent.ConcurrentHashMap[String,String] = {127.0.0.2=mongod-process2, 127.0.0.1=mongod-process1}

尝试再次插入key1 - 插入失败返回value1

scala> res0.putIfAbsent("127.0.0.1", { println("evaluating mongod-process"); "mongod-process1-again" } )
evaluating mongod-process
res7: String = mongod-process1

最终地图

scala> res0
res8: java.util.concurrent.ConcurrentHashMap[String,String] = {127.0.0.2=mongod-process2, 127.0.0.1=mongod-process1}

另外,注意putIfAbsent在开头(ConcurrentHashMap.java:1011)对键值进行空值检查,因此无论如何都必须对值进行评估。

scala> res0.putIfAbsent("127.0.0.1", { println("evaluating mongod-process"); null } )
evaluating mongod-process
java.lang.NullPointerException
  at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
  at java.util.concurrent.ConcurrentHashMap.putIfAbsent(ConcurrentHashMap.java:1535)
  ... 29 elided