64

公式のチュートリアル参照から正確に理解していない先物の側面があります。http://docs.scala-lang.org/overviews/core/futures.html

scalaの先物には、ある種のタイムアウトメカニズムが組み込まれていますか? 以下の例が 5 ギガバイトのテキスト ファイルであるとしましょう... "Implicits.global" の暗黙のスコープにより、最終的に onFailure が非ブロッキングの方法で起動するか、それとも定義できますか? また、何らかのデフォルトのタイムアウトがなければ、成功も失敗も発生しない可能性があることを意味しませんか?

import scala.concurrent._
import ExecutionContext.Implicits.global

val firstOccurence: Future[Int] = future {
  val source = scala.io.Source.fromFile("myText.txt")
  source.toSeq.indexOfSlice("myKeyword")
}
firstOccurence onSuccess {
  case idx => println("The keyword first appears at position: " + idx)
}
firstOccurence onFailure {
  case t => println("Could not process file: " + t.getMessage)
}
4

14 に答える 14

73

ブロッキングを使用してFuture. 非ブロッキング コールバックonCompleteonSuccessまたはを使用する場合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のものであることに注意してください。

于 2013-04-30T16:48:37.900 に答える
23

TimeoutFuture同僚用のクラスを作成しました。

TimeoutFuture

package model

import scala.concurrent._
import scala.concurrent.duration._
import play.libs.Akka
import play.api.libs.concurrent.Execution.Implicits._

object TimeoutFuture {
  def apply[A](timeout: FiniteDuration)(block: => A): Future[A] = {

    val prom = promise[A]

    // timeout logic
    Akka.system.scheduler.scheduleOnce(timeout) {
      prom tryFailure new java.util.concurrent.TimeoutException
    }

    // business logic
    Future { 
      prom success block
    }

    prom.future
  } 
}

使用法

val future = TimeoutFuture(10 seconds) { 
  // do stuff here
}

future onComplete {
  case Success(stuff) => // use "stuff"
  case Failure(exception) => // catch exception (either TimeoutException or an exception inside the given block)
}

ノート:

  • プレイ前提!フレームワーク(ただし、適応するのは簡単です)
  • コードのすべての部分が同じように実行されますが、ExecutionContextこれは理想的ではない可能性があります。
于 2013-06-25T00:15:31.193 に答える
6

Play フレームワークには Promise.timeout が含まれているため、次のようなコードを記述できます。

private def get(): Future[Option[Boolean]] = {
  val timeoutFuture = Promise.timeout(None, Duration("1s"))
  val mayBeHaveData = Future{
    // do something
    Some(true)
  }

  // if timeout occurred then None will be result of method
  Future.firstCompletedOf(List(mayBeHaveData, timeoutFuture))
}
于 2014-12-25T10:14:29.700 に答える
5

これが Scala の標準ではないことに非常に驚いています。私のバージョンは短く、依存関係はありません

import scala.concurrent.Future

sealed class TimeoutException extends RuntimeException

object FutureTimeout {

  import scala.concurrent.ExecutionContext.Implicits.global

  implicit class FutureTimeoutLike[T](f: Future[T]) {
    def withTimeout(ms: Long): Future[T] = Future.firstCompletedOf(List(f, Future {
      Thread.sleep(ms)
      throw new TimeoutException
    }))

    lazy val withTimeout: Future[T] = withTimeout(2000) // default 2s timeout
  }

}

使用例

import FutureTimeout._
Future { /* do smth */ } withTimeout
于 2015-04-10T14:50:49.670 に答える
3

未来を待つときのタイムアウトを指定できます。

の場合scala.concurrent.Futureresultメソッドを使用してタイムアウトを指定できます。

scala.actors.Futureでは、Futures.awaitAllタイムアウトを指定できます。

Future の実行にタイムアウトが組み込まれているとは思いません。

于 2013-04-30T16:23:21.777 に答える
0

Akka システム ディスパッチャーを使用するこのバージョン (上記の Play の例に基づく) を使用しています。

object TimeoutFuture {
  def apply[A](system: ActorSystem, timeout: FiniteDuration)(block: => A): Future[A] = {
    implicit val executionContext = system.dispatcher

    val prom = Promise[A]

    // timeout logic
    system.scheduler.scheduleOnce(timeout) {
      prom tryFailure new java.util.concurrent.TimeoutException
    }

    // business logic
    Future {
      try {
        prom success block
      } catch {
        case t: Throwable => prom tryFailure t
      }
    }

    prom.future
  }
}
于 2018-01-19T15:03:36.460 に答える