2017-01-05 14 views
2

私はExecutionContextのスレッド数を制御したかったのです。だから私はThreadPoolExecutorのインスタンスを作成し、そこからExecutionContextを作成しました。scala.concurrent.Future.on異なるExecutorServiceで実行時間を待つ

そして私はいくつかの未来を作成し、それらにOnSuccessコールバックを添付しました。私は、未来の仕事が終わるたびに、それぞれのonSuccessコールバックが呼び出されることを期待していました。しかし、すべてのonSuccessコールバックが同時に実行されたことがわかりました。

import java.util.concurrent.{ Executors, ForkJoinPool } 

import scala.concurrent.{ Await, ExecutionContext, Future } 
import scala.concurrent.duration.Duration 

object Main extends App { 
    implicit val ec = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(2)) 
    // implicit val ec = ExecutionContext.fromExecutorService(new ForkJoinPool(2)) 

    val start = System.currentTimeMillis() 

    val futures = for { 
    i <- 1 to 10 
    } yield Future[Int] { 
    Thread.sleep(i * 1000) 
    i 
    } 

    futures.foreach { f => 
    f.onSuccess { case i => 
     println(s"${i} Success. ${System.currentTimeMillis() - start}ms elapsed.") 
    } 
    } 

    Await.ready(Future.sequence(futures.toList), Duration.Inf) 
    ec.shutdown() 
} 

// ThreadPoolExecutor Result 
// 1 Success. 25060ms elapsed. 
// 2 Success. 25064ms elapsed. 
// 3 Success. 25064ms elapsed. 
// 4 Success. 25064ms elapsed. 
// 5 Success. 25064ms elapsed. 
// 6 Success. 25064ms elapsed. 
// 7 Success. 25065ms elapsed. 
// 8 Success. 25065ms elapsed. 
// 9 Success. 25065ms elapsed. 
// 10 Success. 30063ms elapsed. 

// ForkJoinPool Result 
// 1 Success. 1039ms elapsed. 
// 2 Success. 2036ms elapsed. 
// 3 Success. 4047ms elapsed. 
// 4 Success. 6041ms elapsed. 
// 5 Success. 12042ms elapsed. 
// 6 Success. 12043ms elapsed. 
// 7 Success. 25060ms elapsed. 
// 8 Success. 25060ms elapsed. 
// 9 Success. 25060ms elapsed. 
// 10 Success. 30050ms elapsed. 

上記の結果は、それぞれ同時に印刷されたものではありません。しかし、ThreadPoolExecutorの代わりにForkJoinPoolを使用すると、この問題は緩和されます。私はExecutionContextとFutureを悪用しましたか?

編集:スレッドの数が未来の数より少ないと問題が発生することがわかりました。上記のコードを編集して問題を再現し、実行時間を印刷しました。

私は私が最終的に将来のコールバック(onCompleteのか、するonSuccess)を設けのExecutionContextのスレッドで実行されていることを知っていた

+0

実行するコードを正確に記入する必要があります。あなたが貼り付けたものは不完全であり、あなたが描写した出力を生成しません。実際、私のために、あなたが見ているものではなく、あなたが期待しているとおりにすべてが機能します。 – Haspemulator

+0

私はちょうど質問を編集しました。問題は、スレッドの数が未来よりも少ない場合に発生します。 – jyshin

+0

各Futureを「blocking」とマークする必要がありますか?[this StackOverflow post](http://stackoverflow.com/questions/19681389/) scala-concurrent-blockingの使用)? – Castaglia

答えて

0

...将来のコールバックは、スレッドの数が少なくても時間通りに呼ばれるべきだと思います。したがって、プール内にアイドル状態のスレッドがない場合、コールバックを実行できませんでした。 See scala.concurrent.Future

しかし、私はまだForkJoinPoolの動作を理解していません。私はそれについて勉強する必要があります。

+0

'ForkJoinPool'はデフォルトで2 *(CPU論理コア)スレッドを使用します。 'nThreads'を同じ番号で置き換えれば、' FixedThreadPool'と同じ結果が得られます。 – Haspemulator

関連する問題