2013-09-06 13 views
27

W dokumencie ScalaDoc jest napisane o współbieżności mapy: "Przestarzałe (od wersji 2.10.0) Zamiast tego użyj scala.collection.concurrent.Map". Niestety, wersja rest of the Scala docs nie została zaktualizowana i nadal nosi numer concurrentMap.Najlepsze praktyki dotyczące mieszania Scala w trybie równoczesnym.Mapa

próbowałem mieszać w concurrent.Map w HashMap, z następującymi wynikami:

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] 

Widzimy więc, że zamiast prostego wstawek, niektóre metody muszą być wdrożone. Czy jest to najlepszy sposób użycia concurrent.Map, czy jest lepszy sposób?

Odpowiedz

34

scala.collection.concurrent.Map cecha jest nie ma być mieszane w z istniejącym zmienny Scala Map do uzyskać wersję wątku mapy instancji bezpiecznej dla wątków. Mieszanka SynchronizedMap istniała w tym celu przed 2.11, ale obecnie jest przestarzała.

Obecnie Scala ma implementację scala.collection.concurrent.TrieMap dla interfejsu scala.collection.concurrent.Map, ale może również owijać klasy Java.

scala.collection.concurrent.Map, w wersji przed 2.10 znanego jako scala.collection.mutable.ConcurrentMap, interfejs jest używany, gdy:

  • chcą zaimplementować własną współbieżne, bezpieczny wątku Map od podstaw

  • chcą zawijać istniejąca implementacja map współbieżnych Java:

Np:

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

val map: concurrent.Map[String, String] = new ConcurrentHashMap().asScala 
  • chcesz napisać kod rodzajowy, który działa jednoczesnych mapy, i nie chcą zobowiązać się do konkretnej realizacji:

Np:

import scala.collection._ 

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

foo(new concurrent.TrieMap) 
foo(new java.util.concurrent.ConcurrentSkipListMap().asScala) 
  • można zaimplementować własną owijkę wokół jednowątkowy zmienny realizacji mapy, naciskając zsynchronizowane (ale trzeba by mieć pewność, że program jest dostęp do zmienny mapę tylko dzięki tej owijki i nigdy bezpośrednio) .

Np .:

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. 
} 
+2

Scala 2.11 odbiera zsynchronizowane cechy. –

+0

Prawda, edytował odpowiedź. – axel22

+0

scala.collection.mutable.ConcurrentMap jest również przestarzałe na rzecz scala.collection.concurrent.Map; wprowadzając tę ​​zmianę w resztę rozwiązania –

10

Jeśli nie chcesz zaimplementować samodzielnie zmieniającej się tablicy skrótów, musisz użyć scala.collection.concurrent.TrieMap.

+0

Co jednoczesnego HashSet i WeakHashMap? –

+3

Nie rozumiem, o co pytasz. –

2

Przez "prosty mixin", być może pytasz, czy cecha może być używana jako dekorator as shown here dla SynchronizedMap, a odpowiedź najwyraźniej nie jest.

Implementacje obejmują TrieMap i opakowanie dla Javy ConcurrentMap (z których istnieją dwie implementacje). (Java oferuje również ConcurrentSkipListSet jako zestaw.)

Zobacz także this roll-your-own question.

Mają Państwo pokryte od strony konwersji rzeczy, jeśli to, czego użyto do:

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 
+0

Widziałem ten przykład zapisany z notacji infiks w innym miejscu. A co z równoczesnymi wersjami HashSet i WeakHashMap? Czy zostały zaimplementowane lub czy istnieje sposób na połączenie zachowania w wersji jednowątkowej? Wolałbym synchronizować poszczególne klucze, nie synchronizować całej kolekcji. –

Powiązane problemy