Scala异步与Java ForkJoinTask

时间:2014-03-25 18:44:06

标签: java scala asynchronous async-await forkjoinpool

前段时间我发现了Scala Async Project。问题是:这个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可以做什么?也许在一些更复杂的情况下?我错过了什么?

1 个答案:

答案 0 :(得分:9)

您发布的两个代码段的工作方式有一个至关重要的区别:阻止操作

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

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

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

另一方面,Java的fork-join pool 中的join方法阻塞了该线程。

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

总结:scala-async的目的是使非阻塞,基于回调的异步处理在语法上与标准的阻塞方法一样自然(就像你在爪哇)。