在Scala concurrent.Map中混合的最佳实践

时间:2013-09-06 14:58:02

标签: scala concurrency hashmap

ScalaDoc说明了关于concurrentMap:"已弃用(自版本2.10.0起)使用scala.collection.concurrent.Map代替。"很遗憾,rest of the Scala docs尚未更新,仍引用concurrentMap

我尝试将concurrent.Map混合到HashMap中,结果如下:

scala> val mmap = new mutable.HashMap[String, String] with collection.concurrent.Map[String, String]
<console>:16: error: object creation impossible, since:
it has 4 unimplemented members.
/** As seen from anonymous class $anon, the missing signatures are as follows.
 *  For convenience, these are usable as stub implementations.
 */
  def putIfAbsent(k: String,v: String): Option[String] = ???
  def remove(k: String,v: String): Boolean = ???
  def replace(k: String,v: String): Option[String] = ???
  def replace(k: String,oldvalue: String,newvalue: String): Boolean = ???

       val mmap = new mutable.HashMap[String, String] with collection.concurrent.Map[String, String]

所以我们看到,除了简单的mixin之外,还必须实现一些方法。这是使用concurrent.Map的最佳方式,还是有更好的方式?

5 个答案:

答案 0 :(得分:41)

scala.collection.concurrent.Map特征并不意味着与现有的可变Scala Map混合以获取地图实例的线程安全版本。 SynchronizedMap之前存在2.11 mixin,但现已弃用。

目前,Scala具有scala.collection.concurrent.TrieMap接口的scala.collection.concurrent.Map实现,但也可以包装Java类。

{1}},在2.10之前的版本中称为scala.collection.concurrent.Map,界面用于:

  • 希望从头开始实现您自己的并发线程安全scala.collection.mutable.ConcurrentMap

  • 想要包装现有的Java并发映射实现:

E.g:

Map
  • 想编写适用于并发映射的通用代码,并且不想提交特定的实现:

E.g:

import scala.collection._
import scala.collection.convert.decorateAsScala._
import java.util.concurrent.ConcurrentHashMap

val map: concurrent.Map[String, String] = new ConcurrentHashMap().asScala
  • 你可以使用synchronized实现你自己的单线程可变映射实现的包装器(但你需要确保你的程序只通过这个包装器访问可变映射,而不是直接访问)。

E.g:

import scala.collection._

def foo(map: concurrent.Map[String, String]) = map.putIfAbsent("", "")

foo(new concurrent.TrieMap)
foo(new java.util.concurrent.ConcurrentSkipListMap().asScala)

答案 1 :(得分:11)

除非您想自己实现并发可变哈希映射,否则必须使用scala.collection.concurrent.TrieMap

答案 2 :(得分:5)

直接取自此评论: https://stackoverflow.com/a/49689669/7082628

2018年,显然你可以这样做:

import java.util.concurrent.ConcurrentHashMap

val m: ConcurrentHashMap[String,MyClass] = new ConcurrentHashMap

答案 3 :(得分:3)

通过“简单混合”,也许你会问这个特质是否可以用作as shown here的装扮SynchronizedMap,答案显然不是。

实现包括TrieMap和Java ConcurrentMap的包装器(其中有两个实现)。 (Java还提供ConcurrentSkipListSet作为Set。)

另见this roll-your-own question

如果您习惯这样做,他们会让您了解转换方面的内容:

scala> import java.util.concurrent._
import java.util.concurrent._

scala> import collection.JavaConverters._
import collection.JavaConverters._

scala> val m = new ConcurrentHashMap[String, Int]
m: java.util.concurrent.ConcurrentHashMap[String,Int] = {}

scala> val mm = m.asScala
mm: scala.collection.concurrent.Map[String,Int] = Map()

scala> mm.replace("five",5)
res0: Option[Int] = None

scala> mm.getClass
res1: Class[_ <: scala.collection.concurrent.Map[String,Int]] = class scala.collection.convert.Wrappers$JConcurrentMapWrapper

答案 4 :(得分:2)

2021 年和 Scala 2.13 的更新:

在包装Java并发映射实现时需要使用不同的隐式转换:

import java.util.concurrent.ConcurrentHashMap
import scala.collection.concurrent
import scala.jdk.CollectionConverters._

val map: concurrent.Map[String, String] = new ConcurrentHashMap().asScala