当前位置: 首页 > 知识库问答 >
问题:

Scala中超时的未来

暴乐邦
2023-03-14

假设我有一个函数,它调用一个阻塞可中断操作。我想在超时的情况下异步运行它。也就是说,我想在超时到期时中断函数。

所以我正在尝试做这样的事情:

import scala.util.Try
import scala.concurrent.Future

def launch(f: () => Unit, timeout: Int): Future[Try[Unit]] = {

  val aref = new java.util.concurrent.atomic.AtomicReference[Thread]() 

  import ExecutionContext.Implicits.global
  Future {Thread.sleep(timeout); aref.get().interrupt} // 1
  Future {aref.set(Thread.currentThread); Try(f())}    // 2
}

问题是 (1) 中的 aref 可以为 null,因为 (2) 尚未将其设置为当前线程。在这种情况下,我想等到 aref 设置完毕。最好的方法是什么?

共有3个答案

储峻
2023-03-14

如果添加一个< code>CountDownLatch,就可以实现您想要的行为。(请注意,在很多很多的< code>Future中发生阻塞(即,在< code>await处停滞)可能会导致线程池的饥饿。)

import scala.util.Try
import scala.concurrent.Future

def launch(f: () => Unit, timeout: Int): Future[Try[Unit]] = {

  val aref = new java.util.concurrent.atomic.AtomicReference[Thread]()
  val cdl = new java.util.concurrent.CountDownLatch(1)

  import ExecutionContext.Implicits.global
  Future {Thread.sleep(timeout); cdl.await(); aref.get().interrupt}   // 1
  Future {aref.set(Thread.currentThread); cdl.countDown(); Try(f())}  // 2
}
向俊贤
2023-03-14

我也需要相同的行为,所以这就是我解决它的方式。我基本上创建了一个对象,该对象创建一个计时器,如果将来未在指定的持续时间内完成,则使用TimeoutException使promise失败。

package mypackage

import scala.concurrent.{Promise, Future}
import scala.concurrent.duration.FiniteDuration
import akka.actor.ActorSystem
import scala.concurrent.ExecutionContext.Implicits.global

object TimeoutFuture {

  val actorSystem = ActorSystem("myActorSystem")
  def apply[A](timeout: FiniteDuration)(block: => A): Future[A] = {
    val promise = Promise[A]()
    actorSystem.scheduler.scheduleOnce(timeout) {
      promise tryFailure new java.util.concurrent.TimeoutException
    }

    Future {
      try {
        promise success block
      }
      catch {
        case e:Throwable => promise failure e
      } 
    }

    promise.future
  }
}
赵英哲
2023-03-14

您可以使用Await实现稍微简单一点的方法。< code>Await.result方法将超时持续时间作为第二个参数,并在超时时引发< code>TimeoutException。

try {
  import scala.concurrent.duration._
  Await.result(aref, 10 seconds);
} catch {
    case e: TimeoutException => // whatever you want to do.
}
 类似资料:
  • 有一个方面的未来,我不完全理解从官方教程参考。http://docs.scala-lang.org/overviews/core/futures.html scala中的期货是否有某种内置的超时机制?假设下面的示例是一个5GB的文本文件...“Implicits.global”的隐含范围最终会导致onFailure以非阻塞方式触发还是可以定义?如果没有某种默认的超时,这是否意味着成功或失败都不会触

  • 我无法使用截击库。我不想无限期地等待请求,所以我不想设置超时。但它不起作用。我在其他地方也有同样的东西(我使用RequestFuture而不是RequestFuture),它运行良好,但在这里我无法将其设置为工作状态。 如果你能提供任何帮助,那就太棒了!谢谢

  • 是否有可能“反转”Scala的未来? 有时候,未来成功的结果意味着错误。在这种情况下,翻转一个未来会很好,即调用一个返回未来的函数,如果最初的未来失败,则该函数以指定的值成功,如果最初的未来成功,则以指定的错误失败。

  • 我有一个scala.html页面,它在Play 2.2.1、Scala 2.10.2、Slick 1.0.1、Postgres 9.3应用程序中调用AJAX。 以下同步代码工作正常。它解析请求查询字符串并调用方法 ,该方法对表进行 scala 光滑调用,并根据 对象过滤结果并返回 如果我将方法改为异步运行(见下文),并多次调用listSchools,那么大约20秒后就会抛出这个异常。我怀疑这可能是

  • Scala中有没有不会失败的< code >未来这个概念? 我正在将可能失败,因此我同时处理和--到,并带有从失败或成功状态派生的可选错误消息。目前为止,一切都好。 现在的情况是,我想正式地(即在类型系统的帮助下)记住,这个未来将始终保持,并且我将来不需要处理失败案例。 有什么聪明的方法可以做到这一点吗?

  • 我正在阅读Scala Cookbook(http://shop.oreilly.com/product/0636920026914.do) 有一个与未来使用相关的例子,涉及理解。 到目前为止,我对理解的理解是,当与一个集合一起使用时,它会产生另一个相同类型的集合。例如,如果每个< code>futureX的类型为< code>Future[Int],则以下内容也应为< code>Future[In