我有两种方法,我们称它们为load()
和init()
。每个人都在自己的线程中启动一个计算,并在其自己的执行上下文中返回Future
。这两个计算是独立的。用回调编写两个Scala未来,没有第三个ExecutionContext
val loadContext = ExecutionContext.fromExecutor(...)
def load(): Future[Unit] = {
Future
}
val initContext = ExecutionContext.fromExecutor(...)
def init(): Future[Unit] = {
Future { ... }(initContext)
}
我想这两个来自一些三线程中调用 - 说这是从main()
- 并且都完成后执行一些其他的计算。
def onBothComplete(): Unit = ...
现在:
- 我不在乎它完成第一
- 我不在乎什么的线程上执行其它计算,除了:
- 我不想阻止两个线程等待另一个线程;
- 我不想阻塞第三个(调用)线程;和
- 我不想为了设置标志而开始第四个线程。
如果我用-内涵,我得到的是这样的:
val loading = load()
val initialization = initialize()
for {
loaded <- loading
initialized <- initialization
} yield { onBothComplete() }
,我得到无法找到一个隐含的ExecutionContext。
我认为这意味着斯卡拉希望第四个线程等待两个期货的完成并设置标志,无论是明确的新的ExecutionContext
还是ExecutionContext.Implicits.global
。所以看起来理解力已经不存在了。
我想我也许可以嵌套回调:
initialization.onComplete {
case Success(_) =>
loading.onComplete {
case Success(_) => onBothComplete()
case Failure(t) => log.error("Unable to load", t)
}
case Failure(t) => log.error("Unable to initialize", t)
}
不幸的是onComplete
也需要一个隐含的ExecutionContext
,我也得到了同样的错误。 (另外,这是难看的,并且从loading
失去错误消息,如果initialization
失败。)
是否有任何方式来组成的Scala期货而不阻塞和不引入另一个ExecutionContext
?如果没有,我可能不得不把它们扔给Java 8 CompletableFutures或
Javaslang
Vavr Futures,它们都能够在执行原始工作的线程上运行回调。
更新澄清阻塞两个等待另一个的线程也是不可接受的。
再次更新对于完成后计算没有那么具体。
你应该做'Future.firstCompletedOf(名单(初始化,加载))'如果你想抓住未来的结果首先完成。为了列表理解将等待两个期货在完成收益之前完成。 – pcting
@pcting在执行其他计算之前,我确实希望等待两个期货的完成。我不想阻止当前的线程来做到这一点。 –
如果这是为了将AtomicBoolean设置为true的确切目的,那么可以改为在完成时指示完成。 'promise.completeWith(初始化zip加载)' –