ブロッキングを使用してFuture
. 非ブロッキング コールバックonComplete
、onSuccess
またはを使用する場合onFailure
は、独自のタイムアウト処理をロールする必要があります。Akka には、アクター間の要求/応答 ( ?
) メッセージングのタイムアウト処理が組み込まれていますが、Akka を使い始めるかどうかはわかりません。FWIW、Akka では、タイムアウト処理のために、実際の非同期タスクを表す 1 つとタイムアウトを表す 1 つをFutures
介して 2 つを一緒に構成します。Future.firstCompletedOf
( 経由の) タイムアウト タイマーHashedWheelTimer
が最初にポップすると、非同期コールバックでエラーが発生します。
独自の展開の非常に単純化された例は、次のようになります。まず、タイムアウトをスケジュールするためのオブジェクト:
import org.jboss.netty.util.{HashedWheelTimer, TimerTask, Timeout}
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.Duration
import scala.concurrent.Promise
import java.util.concurrent.TimeoutException
object TimeoutScheduler{
val timer = new HashedWheelTimer(10, TimeUnit.MILLISECONDS)
def scheduleTimeout(promise:Promise[_], after:Duration) = {
timer.newTimeout(new TimerTask{
def run(timeout:Timeout){
promise.failure(new TimeoutException("Operation timed out after " + after.toMillis + " millis"))
}
}, after.toNanos, TimeUnit.NANOSECONDS)
}
}
次に、Future を受け取り、それにタイムアウト動作を追加する関数:
import scala.concurrent.{Future, ExecutionContext, Promise}
import scala.concurrent.duration.Duration
def withTimeout[T](fut:Future[T])(implicit ec:ExecutionContext, after:Duration) = {
val prom = Promise[T]()
val timeout = TimeoutScheduler.scheduleTimeout(prom, after)
val combinedFut = Future.firstCompletedOf(List(fut, prom.future))
fut onComplete{case result => timeout.cancel()}
combinedFut
}
HashedWheelTimer
ここで使用している は Nettyのものであることに注意してください。