非阻塞如何等待未来10秒钟?

时间:2018-09-28 11:42:58

标签: scala

import scala.concurrent.{Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import scala.util.Random

object Example1 extends App {
    println("starting calculation ...")
    val f = Future {
        sleep(Random.nextInt(500))
        42
    }
    println("before onComplete")
    f.onComplete {
        case Success(value) => println(s"Got the callback, meaning = $value")
        case Failure(e) => e.printStackTrace
    }

    sleep(2000)
}

使用Await.ready,我们可以等待10秒钟,如果将来还没有完成,它将抛出TimeoutException。但是Await.ready正在阻止。如上例所示,使用回调时等待10秒的最佳方法是什么?(不使用Akka之类的框架)

1 个答案:

答案 0 :(得分:2)

令人难以置信,但是scala标准库不包含此功能:( 可以使用其他Future实现方式-类似于com.twitter.util.Futurescalaz.concurrent.Future,但是使用标准scala Future时,您无法立即使用它。

您可以自己实现它,但这看起来有点难看:(

  object FutureCancellator {
    val scheduler = ??? // You can use whatever scheduler available within your system - like akka scheduler or whatever, or roll your own, based on a timer thread.

     class Within[T](val f: Future[T]) extends AnyVal {
        def within(d: Duration): Future[T] = {
           val timeout: Future[T] = scheduler.after(d) { _ => 
              throw new TimeoutException(e)
           }
           Future.firstCompletedOf(f, timeout)
        }         
     }
  }

现在,您可以执行以下操作:

 import FutureCancellator._
 import scala.concurrent.duration._

 someFuture
   .within(10 seconds)
   .onComplete {
      case Success(foo) => println(s"got $foo")
      case Failure(t: TimeoutException) => println("timeout")
      case Failure(e) => e.printStackTrace
   }