我将这个HashMap数组定义如下
var distinctElementsDefinitionMap: scala.collection.mutable.ArrayBuffer[HashMap[String, Int]] = new scala.collection.mutable.ArrayBuffer[HashMap[String, Int]](300) with scala.collection.mutable.SynchronizedBuffer[HashMap[String, Int]]
现在,我有一个300个元素的并行集合
val max_length = 300
val columnArray = (0 until max_length).toParArray
import scala.collection.parallel.ForkJoinTaskSupport
columnArray.tasksupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(100))
columnArray foreach(i => {
// Do Some Computation and get a HashMap
var distinctElementsMap: HashMap[String, Int] = //Some Value
//This line might result in Concurrent Access Exception
distinctElementsDefinitionMap.update(i, distinctElementsMap)
})
我现在正在上面定义的foreach
的{{1}}循环内运行计算密集型任务。
计算完成后,我希望每个线程都更新columnArray
数组的特定条目。
每个线程只更新特定的索引值,对执行它的线程是唯一的。
我想知道这个数组条目的更新是否安全,多个线程可能同时写入它?
如果不是,有distinctElementsDefinitionMap
方式这样做,那么它是否是线程安全的?
谢谢!
更新:
看来这真的不是安全的方法。我得到synchronized
有关如何在使用并行集合时避免这种情况的任何提示。
答案 0 :(得分:0)
使用.groupBy
操作,据我所知it is parallelized(与其他方法不同,例如.sorted
)
case class Row(a: String, b: String, c: String)
val data = Vector(
Row("foo", "", ""),
Row("bar", "", ""),
Row("foo", "", "")
)
data.par.groupBy(x => x.a).seq
// Map(bar -> ParVector(Row(bar,,)), foo -> ParVector(Row(foo,,), Row(foo,,)))
希望你明白了。
或者,如果你的RAM允许你,并行处理每列而不是行,那么它必须比你当前的方法更有效(争用更少)。
val columnsCount = 3 // 300 in your case
Vector.range(0, columnsCount).par.map { column =>
data.groupBy(row => row(column))
}.seq
虽然单列可能会出现内存问题(8M行可能会非常多)。