问题 Scala异步与Java ForkJoinTask


前段时间我发现了 Scala异步项目。问题是:在这方面有多么神奇 async 通过普通函数无法实现的块(没有宏扩展)?

让我们看一下介绍中的第一个例子:

import ExecutionContext.Implicits.global
import scala.async.Async.{async, await}

val future = async {
    val f1 = async { ...; true }
    val f2 = async { ...; 42 }
    if (await(f1)) await(f2) else 0
}

我在上面的例子中看不到任何不能用纯Java编写的东西。这段代码完全相同:

import java.util.concurrent.*;
import java.util.function.Supplier;

// First define a helper method for creating async blocks:
public static <T> ForkJoinTask<T> async(Supplier<T> supplier) {
    return new RecursiveTask<T>() {
        @Override
        protected T compute() {
            return supplier.get();
        }
    }.fork();
}

ForkJoinTask<Integer> future = ForkJoinPool.commonPool().submit(() -> {
    ForkJoinTask<Boolean> f1 = async(() -> true);
    ForkJoinTask<Integer> f2 = async(() -> 42);

    if (f1.join()) {
        return f2.join();
    } else {
        return 42;
    }
});

什么可以Scala async 那Java不行吗?也许在一些更复杂的情况下?我错过了什么?


11336
2018-03-25 18:44


起源

我认为Scala中的“任何东西”都可以重写为Pure Java ..给予足够的时间和精力:| - user2864740
FYI 它不直接回答java部分,但无论如何 - om-nom-nom
@ user2864740和任何用Java编写的东西都可以在纯汇编程序中重新实现:-) - om-nom-nom
哪个代码看起来更简洁? - GriffeyDog
不,必须有一个杀手级的功能 async 除了语法。我想到的一个想法是 async 适用于任何线程池,不是必需的 ForkJoinPool。 - ZhekaKozlov


答案:


你发布的两个片段在幕后工作方式有一个至关重要的区别: 阻止操作

scala-async 代码段大致相当于:

val future = {
  val f1 = Future { ...; true }
  val f2 = Future { ...; 42 }
  f1.flatMap { b =>
    if(b) f2 else Future.successful(0)
  }
}

这是一个基于回调的代码。那里没有可以阻止任何线程的操作。只有未来的包装和回调注册(发生在引擎盖下) flatMap 在这种情况下)。换句话说,一切都是 异步 那里。

另一方面, join 来自Java的fork-join池的方法  阻止线程。

没有阻塞操作是一个重要的性能/可伸缩性优势,因为 - 极大地简化 - 无阻塞=>需要更少的线程=>所需的OS资源更少+上下文切换更少。

总结:目的 scala-async 是基于非阻塞,回调, 异步 处理语法中的自然作为标准的阻塞方法(就像你在Java中使用的那样)。


9
2018-03-25 19:45



我认为 await 会阻止调用它的线程。 - njzk2
@ njzk2不,它没有,这就是所有宏魔法的全部要点 scala-async 确实。 - ghik
怎么可能等待实际上没有等待答案?即,如何继续执行,具体取决于线程计算所述值尚未计算的值? - njzk2
@ njzk2 await 只在“语法上”等待 - 它看起来像一个阻塞调用,同时在引擎盖下是非阻塞的。什么 真 发生了一个“延续”回调被注册。这种转换发生在编译时(await 和 async 是 宏,而不是实际的方法调用)。 - ghik
@ njzk2调查一下 消息来源  - 它明确指出 await 电话被转换为 onComplete 呼叫由 await 宏。 - ghik