正如丹尼尔写道,尝试用Double编写Java风格的部分问题来自于Scala中的Double
是scala.Double
而不是java.lang.Double
。如果你想在风格的Java编程,你将不得不大意如下走:
//
// a) Java style, with concurrency problem
//
import java.lang.{Double=>JDouble}
import java.util.concurrent.ConcurrentHashMap
val map = new ConcurrentHashMap[String, JDouble]
def update(name: String, time: Double) {
val value: JDouble = map.get(name)
if (value eq null)
map.put(name, time)
else
map.put(name, JDouble.valueOf(value.doubleValue + time))
}
update("foo", 42.0d)
update("foo", 41.0d)
assert(map.get("foo") == 83.0d)
斯卡拉2.8中包含Scala的包装为ConcurrentMap
S,所以你可以很容易地避免java.lang.Double
问题VS scala.Double
。我会保持一段时间的程序结构。
//
// b) Scala style, with concurrency problem.
//
import collection.JavaConversions._
import collection.mutable.ConcurrentMap
import java.util.concurrent.ConcurrentHashMap
val map: ConcurrentMap[String, Double] = new ConcurrentHashMap[String,Double]()
def update(name: String, time: Double) {
map.get(name) match {
case None => map.put(name, time)
case Some(value) => map.put(name, value + time)
}
}
update("foo", 42.0d)
update("foo", 41.0d)
assert(map("foo") == 83.0d)
在变型b)中不存在表示缺少的值作为0.0D非彼java.lang.Double
不与运营商和拳击发挥很好的问题既没有问题。但是,a)和b)版本对于它们的并发行为都存在疑问。 Mansoor的代码使用ConcurrentHashMap
,其目的是允许同时访问地图。在原始版本的代码中,有可能在获取旧的value
和存储value + time
之间丢失地图更新。 以下变体c)试图避免这个问题。
//
// c) Scala style, hopefully safe for concurrent use ;)
//
import collection.JavaConversions._
import collection.mutable.ConcurrentMap
import java.util.concurrent.ConcurrentHashMap
val map: ConcurrentMap[String, Double] = new ConcurrentHashMap[String,Double]()
def update(name: String, time: Double) {
val valueOption: Option[Double] = map.putIfAbsent(name, time)
def replace(value: Double) {
val replaced = map.replace(name, value, value + time)
if (!replaced) {
replace(map(name))
}
}
valueOption foreach { replace(_) }
}
update("foo", 42.0d)
update("foo", 41.0d)
assert(map("foo") == 83.0d)
谢谢你的解释 – 2010-06-08 16:02:20