在其他未来完成未来

时间:2016-09-20 13:41:18

标签: scala concurrency

我有一个外部未来操作,我可以覆盖它的onOperation完成方法。我想通过关闭 Promise 来包装它并完成。但是,在其他未来,我无法完成未来。例如:

import scala.concurrent.{Future, Promise}
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
def foo():Future[String] = {
  val p = Promise[String]()
  channel.addListener(new ChannelFutureListener[IoReadFuture] {
    override def operationComplete(future: IoReadFuture): Unit = {
     p.success("hello")}
  }
  p.future
}

val x = foo()
x: scala.concurrent.Future[String] = List()
x.onComplete{
  case Success(msg)  => println(s"$msg world")
  case Failure(e) => println(e.getMessage)
}
res1: Unit = ()

是否有惯用的方法不阻止

2 个答案:

答案 0 :(得分:0)

我认为您正在尝试创建一个以delay作为输入并返回delayed future的函数。

如果您想这样做,可以使用AwaitPromise以非睡眠的方式执行此操作。

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Promise}
import scala.concurrent.duration._


// returns a future delayed by `delay` seconds
def getDelayedFutureOfStringValue(delay: Int, value: String): Future[String] = {
  // we will use this promise for wait only
  val waitProxyPromise = Promise[Int]()
  val delayedFuture = Await.ready(waitProxyPromise.future, delay.second).map({
    case _ => value
  })
  delayedFuture
}

val helloFuture = getDelayedFutureOfStringValue(2, "hello")

上面的amy看起来像是一个不错的实现,但实际上并非如此。 Await实际上阻止了该线程。可悲的是......在惯用的Scala中,以一种完全无阻塞的方式获取delayedFutue并不容易。

使用Java中的Timer实用程序

可以获得一个很好的非阻塞和非睡眠延迟的未来
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Promise}
import java.util.{Timer, TimerTask}

// delay is number of seconds
def getDelayedFutureOfStringValue(delay: Int, value: String): Future[String] = {
  val promise = Promise[String]()
  val timer = new Timer()
  val timerTask = new TimerTask {
    override def run(): Unit = promise.success(value)
  }
  timer.schedule(timerTask, delay * 1000)
  promise.future
}

val niceHelloFuture = getDelayedFutureOfStringValue(2, "hello")

如果你已经和你有了未来,而你想用它来构建一个依赖的未来,那么它很容易。

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

// I assume you IoReadFuture is either similar to Future or wraps the actual Future   

def foo(value: String):Future[String] = {
  val p = Promise[String]()
  channel.addListener(new ChannelFutureListener[IoReadFuture] {
    override def operationComplete(ioFuture: IoReadFuture): Unit = {
      ioFuture.future.onComplete(_ => p.success(value))
    }
  }
  p.future
}

答案 1 :(得分:0)

actor调度程序的

scheduleOne是阻塞某些代码执行的非阻塞方式

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

val p = Promise(doSomething())
val system = akka.actor.ActorSystem("system")
system.scheduler.scheduleOne(deplay seconds)(p.future)
val f = p.future
f.flatMap { println(s"${_}") }