在Scala concurrent.Map中混合的最佳实践 [英] Best practices for mixing in Scala concurrent.Map

查看:415
本文介绍了在Scala concurrent.Map中混合的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ScalaDoc 对concurrentMap说:已弃用(从版本2.10.0开始)使用 scala.collection.concurrent.Map 。很抱歉,其他Scala文档尚未更新仍然引用 concurrentMap



我试图混合在 concurrent.Map 转换为 HashMap ,结果如下:

  Scala> val mmap = new mutable.HashMap [String,String] with collection.concurrent.Map [String,String] 
< console>:16:error:对象创建不可能,因为:
它有4未实现成员。
/ **从匿名类$ anon可以看出,缺少的签名如下。
*为了方便,这些可用作存根实现。
* /
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]

所以我们看到,而不是一个简单的混合,一些方法也必须实现。这是使用 concurrent.Map 的最好方法,还是有更好的方法?

解决方案

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



目前,Scala对 scala.collection.concurrent.Map scala.collection.concurrent.TrieMap 实现c $ c> interface



scala.collection.concurrent.Map ,在2.10之前的版本称为 scala.collection.mutable.ConcurrentMap ,当您使用接口时:




  • 希望从头开始实现自己的并发,线程安全映射


  • 想要包装现有的Java并发地图实现:




例如:

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

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


$ b b


  • 要写出能够同时处理地图的通用代码,并且不想提交到特定实现:



例如:

  import scala.collection._ 

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

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




  • 线程可变映射实现(但是你需要确保你的程序只通过这个包装器访问可变映射,而不是直接访问)。



例如:

  class MySynchronizedMap [K,V](private val underlying:mutable.Map [K,V ] 
extends concurrent.Map [K,V] {
private val monitor = new AnyRef
def putIfAbsent(k:K,v:V):Option [String] = monitor.synchronized {
underlying.get(k)match {
case s:Some [V] => s
case无=>
underlying(k)= v

}
}
def remove(k:K,v:V):Boolean = monitor.synchronized {
underlying.get(k)match {
case Some(v0)if v == v0 => underlying.remove(k); true
case无=> false
}
}
//等
}


The ScalaDoc says this about concurrentMap: "Deprecated (Since version 2.10.0) Use scala.collection.concurrent.Map instead." Unfortunately, the rest of the Scala docs has not been updated and still references concurrentMap.

I tried to mix in concurrent.Map into a HashMap, with the following results:

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]

So we see that instead of a simple mixin, some methods must also be implemented. Is this the best way to use concurrent.Map, or is there a better way?

解决方案

The scala.collection.concurrent.Map trait is not meant to be mixed-in with an existing mutable Scala Map to obtain a thread-safe version of the map instance. The SynchronizedMap mixin existed for this purpose before 2.11, but is now deprecated.

Currently, Scala has the scala.collection.concurrent.TrieMap implementation for the scala.collection.concurrent.Map interface, but can wrap Java classes as well.

The scala.collection.concurrent.Map, in versions prior to 2.10 known as scala.collection.mutable.ConcurrentMap, interface is used when you:

  • want to implement your own concurrent, thread-safe Map from scratch

  • want to wrap an existing Java concurrent map implementation:

E.g:

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

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

  • want to write generic code that works concurrent maps, and don't want to commit to a specific implementation:

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)

  • you could implement your own wrapper around a single-threaded mutable map implementation by using synchronized (but you would need to ensure that your program is accessing the mutable map only through this wrapper and never directly).

E.g.:

class MySynchronizedMap[K, V](private val underlying: mutable.Map[K, V])
extends concurrent.Map[K, V] {
  private val monitor = new AnyRef
  def putIfAbsent(k: K,v: V): Option[String] = monitor.synchronized {
    underlying.get(k) match {
      case s: Some[V] => s
      case None =>
        underlying(k) = v
        None
    }
  }
  def remove(k: K, v: V): Boolean = monitor.synchronized {
    underlying.get(k) match {
      case Some(v0) if v == v0 => underlying.remove(k); true
      case None => false
    }
  }
  // etc.
}

这篇关于在Scala concurrent.Map中混合的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆