11

しばらく前に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;
    }
});

Scalaasyncにできて Java にできないことは? たぶん、もっと複雑なシナリオの場合は?何が恋しいですか?

4

1 に答える 1

9

投稿した 2 つのスニペットが内部でどのように機能するかには、1 つの重要な違いがあります。ブロッキング操作です。

このscala-asyncスニペットは、次とほぼ同等です。

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

これはコールバック ベースのコードです。スレッドをブロックする操作はありません。将来のラッピングとコールバックの登録のみ (flatMapこの場合は の内部で発生します)。つまり、そこではすべてが非同期です。

一方、joinJava の fork-join プールのメソッドスレッドをブロックします。

ブロッキング操作がないことは、パフォーマンス/スケーラビリティの大きな利点です。なぜなら、大幅に簡素化 - ブロッキングがない => 必要なスレッドが少ない => 必要な OS リソースが少ない + コンテキストの切り替えが少ないからです。

要約: の目的は、scala-asyncノンブロッキング、コールバック ベース、非同期処理を標準のブロッキング アプローチ (Java で使用したものなど) と同じくらい自然な構文にすることです。

于 2014-03-25T19:45:00.553 に答える