3

Groovy スレッドに質問があります。

私の仕事は、特定のディレクトリ内の各ファイルを特定の方法で変換し、結果の出力を別のディレクトリ内のファイルに配置することです。

私は動作する次のコードを書きました:

static def translateDir(fromDir, targetDir) {
    def allFiles = new File(fromDir).listFiles()
    def numFiles = allFiles.length

    for (i in 0..(numFiles - 1))
        translate(allFiles[i].getAbsolutePath(), targetDir)
}

今、私はこのコードを次のように並列化しようとしました:

static def translateDir(fromDir, targetDir) {
    def allFiles = new File(fromDir).listFiles()
    def numFiles = allFiles.length
    def numCores = Runtime.getRuntime().availableProcessors()

    for (i in 0..(numCores - 1)) {
        println("Thread " + i + "starting")
        Thread.start {
            for (def j = i; j < numFiles; j += numCores) {
                println("j = " + j) 
                translate(allFiles[j].getAbsolutePath(), targetDir)
            }
        }
    }
}

これは機能せず、出力を提供します:

Thread 0 starting
Thread 1 starting
Thread 2 starting
Thread 3 starting

私のテストケースでは、nunCores は 4 で、numFiles は 3 です。ここで何が起こっているのですか?

4

2 に答える 2

11

スレッドを開始していますが、実行前にプログラムが終了します。

ドキュメントに示されているようjoinに、スレッドが完了するのを待つためにスレッドを呼び出す必要があります

同じページのさらに下に示されているエグゼキュータ フレームワークを使用する方がおそらく簡単です。


編集

楽しみのために、Thread.startあなたが達成しようとしていることを行う何かを実装しました

// This will perform the task required for a list of files
def translate( List files ) {
  files.each {
    // We will just print it out, and sleep for a bit
    println it
    Thread.sleep( 300 )
  }
}

// makeWorker returns a closure that will process the files
def makeWorker( List files ) {
  { -> translate( files ) }
}

// Main processing function
void process( List files ) {
  int numCores = Runtime.getRuntime().availableProcessors()
  // Split the files to process into groups (one for each worker)
  def partitioned = (0..<numCores).collect { i ->
    files[ (i..<files.size()).step( numCores ) ]
  }
  // Then create a Thread for each group
  def threads = partitioned.collect { group ->
    Thread.start makeWorker( group )
  }
  // And wait for them all to finish
  threads*.join()
}

// Simulate the process with the letters a through z
process( 'a'..'z' )
于 2012-05-28T22:13:47.630 に答える
8

わかりました、2つのこと:

  1. スレッドの暗黙的な run() メソッド内で、'i' 変数を参照しています。何が起こるかを正確に確認するには、デバッガーを介して実行する必要がありますが、技術的には、最終的なものではないため、そこにある「i」にアクセスすることさえできません。したがって、コンストラクターで「i」を渡す Runnable オブジェクトを作成することをお勧めします。次に、スレッドでランナブルを開始します。

  2. Groovy には優れた同時実行サポートがあります。このように自分でロールバックする理由はありません。GParsを見てください

于 2012-05-28T22:12:14.530 に答える