6

タスクに並列配列を使用したいのですが、コーディングを開始する前に、この小さなスニペットがスレッドセーフかどうかを知りたいと思います。

import collection.mutable._

var listBuffer = ListBuffer[String]("one","two","three","four","five","six","seven","eight","nine")
var jSyncList  = java.util.Collections.synchronizedList(new java.util.ArrayList[String]())
listBuffer.par.foreach { e =>
    println("processed :"+e)
    // using sleep here to simulate a random delay
    Thread.sleep((scala.math.random * 1000).toLong)
    jSyncList.add(e)
}
jSyncList.toArray.foreach(println)

並列コレクションで何かを処理し、結果を別の場所に蓄積するより良い方法はありますか?

4

5 に答える 5

6

投稿したコードは完全に安全です。ただし、前提についてはよくわかりません。並列コレクションの結果を非並列コレクションに蓄積する必要があるのはなぜですか? 並列コレクションの全体的なポイントの 1 つは、それらが他のコレクションのように見えることです。

seq並列コレクションは、順次コレクションに切り替える方法も提供すると思います。したがって、おそらくこれを使用する必要があります。

于 2011-05-07T12:20:32.113 に答える
2

これsynchronisedListは安全なはずですが、println予期しない結果が生じる可能性があります。アイテムが印刷される順序、または printlns が文字の途中でインターリーブされないという保証はありません。

同期されたリストも、これを行うための最速の方法である可能性は低いです。より安全な解決策はmap、不変のコレクション (Vectorおそらくここでの最善の策です) を超えてから、すべての行を (順番に) 後で出力することです。

val input = Vector("one","two","three","four","five","six","seven","eight","nine")
val output  = input.par.map { e =>
  val msg = "processed :" + e
  // using sleep here to simulate a random delay
  Thread.sleep((math.random * 1000).toLong)
  msg
}
println(output mkString "\n")

また、このコードには、例と同じくらい実用的な有用性があることにも注意してください:)

于 2011-05-07T12:28:41.360 に答える
2

このコードは明らかに奇妙です。同期が必要なものに並列に追加する必要があるのはなぜでしょうか。競合を追加しても、見返りはまったくありません。

事の原則fold- 並列処理からの結果の蓄積は、 、reduceまたはaggregate.

于 2011-05-07T17:19:55.860 に答える
2

投稿したコードは安全です。配列リストへのアクセスが同期されているため、配列リストの状態に一貫性がないためにエラーが発生することはありません。

ただし、並列コレクションは項目を並行して (同時に) 処理し、かつ順不同で処理します。順不同とは、54. 要素が 2. 要素の前に処理される可能性があることを意味します。同期された配列リストには、事前定義されていない順序でアイテムが含まれます。

一般に、コレクションを別のコレクションに変換するにはmap、およびその他の関数コンビネータを使用することをお勧めします。これらにより、コレクションにいくつかのコレクションがある場合 ( s のように) filter、順序の保証が確実に保持されます。Seq例えば:

ParArray(1, 2, 3, 4).map(_ + 1)

常に戻りますParArray(2, 3, 4, 5)

ただし、 や同期コレクションなどの特定のスレッド セーフなコレクション タイプをConcurrentSkipListMapAPI のメソッドに渡す必要がある場合は、並列 foreach から変更するのが安全です。

最後に、注意 - 並列コレクションは、データに対する並列一括操作を提供します。可変並列コレクションは、異なるスレッドから要素を追加できるという意味で、スレッドセーフではありません。マップへの挿入やバッファの追加などの変更可能な操作は、引き続き同期する必要があります。

于 2011-05-08T08:47:14.703 に答える