2016-10-10 12 views
1

私は現在、将来のコンパニオンオブジェクトを拡張するためのコードを書いています。私が実装する一つの機能は、私がScala FutureとThread.sleepの奇妙な振る舞い

test("A list of Futures return only the first computed value") { 
    val nums = (0 until 10).toList 
    val futures = 
     nums map { n => Future { Thread.sleep(n*1000); n } } 

    val v = Await.result(Future.any(futures), Duration.Inf) 

    assert(v === 0) 
    } 

しかし、私は(n+1)*1000n*1000に眠っている時間を切り替えた場合、戻り値は1、ない0で、それを自分のコードをテストしてみましたAny

//returns the future that computes the first value computed from the list. If the first one fails, fail. 
def any[T](fs: List[Future[T]]): Future[T] = { 
    val p = Promise[T]() 

    fs foreach { f => { 
    f onComplete { 
     case Success(v) => p trySuccess v 
     case Failure(e) => p tryFailure e 
    } 
    } } 

    p.future 
} 

です正常に動作します(0を返します)。

0でスリープと呼ばれると特別な効果はありますか?

答えて

1

Thread.sleepは、Futureのブロック操作ですが、実行中であることをExecutionContextに通知していないため、使用するExecutionContextの種類とマシンのプロセッサ数によって動作が異なります。 ExecutionContext.globalで期待どおりblockingを追加した場合、あなたのコードは動作します:

nums map { n => Future { blocking { Thread.sleep(n*1000); n } } } 
+0

ああ、私は 'blocking'ブロックを追加するのを忘れていました。私はこれらのスレッドが実行コンテキストで実行されていることを忘れていました。あなたのソリューションは完全にうまく動作します。ありがとう。 –

0

私は関数名はので、私はあなたがany正しい方法を実装すると思うanyだと思います。 しかし、最初のものが必要ならば、List引数fsから最初の要素を取得し、約束してください。

+0

私はコメントの中で "first"という言葉を誤解したと思う。私は、そして、要件が記述したいと思っていました - 時間領域で最初に計算された値を返します。私は、この実装が要件を満たすことはかなり確信しています。 –