従来のスレッドを超えて: Java Loom コルーチン (ファイバー/仮想スレッド) の無限の可能性を探る

「従来のスレッドを超えて: Java Loom コルーチン (ファイバー/仮想スレッド) の無限の可能性を探る」

1. Javaコルーチンの開発経緯

Java コルーチンの開発プロセスは次の段階に要約できます。

  • コルーチンの概念は 1963 年に正式に提案され、その誕生はスレッドよりもさらに早かった。
  • 2007 年に、バイトコード拡張テクノロジに基づいた Java コルーチン フレームワークである Kilim プロジェクトがリリースされました。
  • 2014 年に、エージェント テクノロジに基づく Java コルーチン フレームワークである Quasar プロジェクトがリリースされました。
  • 2016 年に、Java のネイティブ コルーチン サポートを提供することを目的としたプロジェクトである Project Loom プロジェクトが開始されました。
  • 2019 年に、Kotlin 言語はバージョン 1.3 をリリースしました。これは、コルーチン プログラミングをサポートする Java 互換言語です。
  • 2020 年には、仮想スレッド (仮想スレッド) やスコープ変数などの機能を提供する Project Loom のプレビュー版 (プレビュー機能) を含む Java 15 がリリースされます。
  1. 初期の試み: Java の初期バージョンでは、同時実行性は主にスレッドと同期メカニズムによって実現されていました。Java はマルチスレッドをサポートしていますが、スレッドの作成と切り替えのコストが高いため、同時実行性の高いシーンの処理効率が低くなります。
  2. Quasar (2011): Quasar は、Parallel Universe によって開発されたバイトコード操作とバイトコード インストルメンテーションに基づく Java コルーチン ライブラリです。バイトコードを操作して軽量のコルーチンとタスクの切り替えを実現することにより、Java でコルーチンのような概念を実装します。Quasar は、複数のコルーチンを 1 つのスレッドで実行できるようにするコルーチン プログラミング メソッドを提供し、それによってスレッド切り替えのオーバーヘッドを回避します。
  3. Kotlin Coroutines (2017): Kotlin は、JetBrains によって開発された、JVM 上で実行されるプログラミング言語です。Kotlin Coroutines は、コルーチン方式で非同期コードを作成できる Kotlin 用の非同期プログラミング フレームワークです。Kotlin はスタンドアロンのプログラミング言語ですが、Java とシームレスに統合されるため、Java プロジェクトで Kotlin コルーチンを使用できます。
  4. Project Loom (進行中): Project Loom は、Java に軽量スレッド (仮想スレッドまたは Loom スレッドと呼ばれる) を導入することに特化した OpenJDK のサブプロジェクトです。Loom の目標は、既存の Java プログラムを変更せずに Java にファイバー機能を追加することです。Loom の設計目標は、効率的で使いやすいコルーチンと軽量のスレッド モデルを実装して、Java 同時プログラミングの課題を解決することです。

Java 標準ライブラリにはまだコルーチンのネイティブ サポートがありません。しかし、上記のプロジェクトやライブラリの出現は、Java コミュニティがコルーチン プログラミングの探索と実践だけでなく、効率的な並行プログラミングを求めていることを示しており、今後の Java の開発では、開発者に提供するために、より高度な並行性メカニズムがさらに導入される可能性があります。よりエレガントで効率的な同時プログラミング エクスペリエンス。

二、Java Project Loom

Java Project Loom は Java 言語の重要なプロジェクトであり、軽量スレッド (軽量スレッド) をサポートするように Java 仮想マシン (JVM) の実行モデルを改善し、それによって同時プログラミングおよび並列プログラミングを処理する Java のパフォーマンスとスケーラビリティを向上させることを目的としています。スケーラビリティ。この記事では、Java Project Loom の背景、目標、主な機能、および Java 開発者とアプリケーションへの影響について説明します。

1. 背景

Java 開発では、スレッド (Thread) は、複数の独立した実行パスでプログラムを同時に実行できるようにする、一般的に使用される同時実行メカニズムです。ただし、従来の Java スレッド モデルにはいくつかの問題があります。各スレッドはオペレーティング システムのネイティブ スレッドにマップされるため、スレッドの作成と破棄に高いオーバーヘッドが発生します。また、各スレッドは一定量のメモリ空間を占有するため、同時実行性が高い場合、多数のスレッドを作成すると過剰なメモリ消費が発生し、システムがクラッシュする可能性があります。

これらの問題を解決するために、Java Project Loom プロジェクトが誕生しました。

Java Project Loom の主な目標は、「Fibers」と呼ばれる軽量のスレッド実装を導入して、Java スレッドの管理と実行モデルを最適化することです。ファイバーは、Java 仮想マシン (JVM) およびランタイム システムによって管理されるユーザー モード スレッドであり、オペレーティング システムのネイティブ スレッドにマップする必要はなくなりました。このようにして、ファイバーの作成と破棄のオーバーヘッドが大幅に削減され、多数のファイバーを同じオペレーティング システム スレッド内で実行できるため、メモリ消費が削減され、パフォーマンスが向上します。

2. 主な特長

Java Project Loom は多くの重要な機能をもたらしますが、その中で最も注目すべき機能は次のとおりです。

2.1. 繊維

ファイバーは Java Project Loom の中核機能です。これらは、Fibre API を通じて作成、一時停止、再開、キャンセルできる軽量のユーザーランド スレッド実装です。従来のスレッドと比較して、Fibre の作成および破棄のコストが低く、スレッド リソースを効率的に再利用できるため、アプリケーションは大きなメモリ オーバーヘッドを発生させることなく、数千または数百万の Fiber を同時に実行できます。

2.2. Continuations(续体)

Fiber をサポートするために、Java Project Loom は Continuation の概念を導入しました。継続により、ファイバの実行状態を一時停止中に保存し、必要に応じて一時停止状態に戻すことができます。これにより、ファイバーを一時停止および再開するための効率的なメカニズムが提供され、従来のスレッド コンテキスト切り替えのオーバーヘッドが回避されます。

2.3. 仮想スレッド

Java Project Loom では、ファイバーを透過的にカプセル化するメカニズムである仮想スレッドの概念も導入されています。仮想スレッドはアプリケーションのニーズに応じてファイバーを動的に作成および管理できるため、開発者はスレッド管理の詳細を気にすることなく、シンプルなプログラミング モデルを使用して大規模な同時実行を処理できます。

2.4. スコープ付きスレッド

スコープ付きスレッドは Java Project Loom のもう 1 つの重要な機能であり、これによりファイバーを限られたスコープ内で実行できるようになります。このようにして、ファイバーはスコープ外に出ると自動的に破棄されるため、リソースのリークやスレッド管理の複雑さが回避されます。

3. Project Loomの影響

Java Project Loom の導入は、Java 開発者とアプリケーションに大きな影響を与えます。

3.1. より高い同時パフォーマンス

軽量のファイバーを導入することにより、Java Project Loom は Java アプリケーションが多数の同時タスクをより効率的に処理できるようになり、それによって同時パフォーマンスと拡張性が向上します。

3.2. メモリ消費量の削減

ファイバーをオペレーティング システムのネイティブ スレッドにマッピングする必要がなくなるため、特に同時実行性の高いシナリオでは、Java アプリケーションのメモリ消費量が大幅に削減されます。これは、リソースに制約のある環境やクラウド コンピューティング プラットフォームにとって特に重要です。

3.3. より簡潔なコード

仮想スレッドとスコープ スレッドの導入により、同時プログラミングのコード ロジックが簡素化され、開発者は基礎となるスレッド管理にあまり注意を払わずにビジネス ロジックに集中できるようになります。

3.4. 応答性の向上

Java Project Loom の改善により、Java アプリケーションの応答性が向上し、特に高負荷および同時実行性が高い場合でも、アプリケーションはユーザーのリクエストに迅速に応答できます。

全体として、Java Project Loom は、Java 言語の同時実行性とパフォーマンスの向上に向けた重要なステップです。Fibers と関連機能の導入により、Java 開発者により強力なツールが提供され、効率的で同時実行性の高い Java アプリケーションの開発が容易になります。Java エコシステムの継続的な発展に伴い、Java Project Loom は Java 開発に不可欠かつ重要な部分になることは間違いありません。

4、サンプル

多くのアプリケーションは Thread API を直接使用せず、代わりに java.util.concurrent.ExecutorService および Executors API を使用します。Executor API は、タスクごとに新しいスレッドを開始する ExecutorServices の新しいファクトリ メソッドで更新されました。仮想スレッドは、タスクごとに新しい仮想スレッドを作成できるほど安価であり、仮想スレッドをプールする必要はありません。

以下は、メッセージを出力するためのダミー スレッドを開始します。join メソッドを呼び出して、スレッドが終了するのを待ちます。

スレッド thread = Thread.ofVirtual().start(() -> System.out.println("Hello")); 
thread.join();

以下は、スリープ後に要素をキューに入れるダミー スレッドを開始する例です。メインスレッドはキュー上でブロックされ、要素を待機します。

var queue = new SynchronousQueue<String>(); 
Thread.ofVirtual().start(() -> { 
    try { 
        Thread.sleep(Duration.ofSeconds(2)); 
        queue.put("done"); 
    } catch (InterruptedException e) { } 
}); 
 
文字列 msg = queue.take();

Thread.Builder API を使用して ThreadFactory を作成することもできます。次のスニペットによって作成された ThreadFactory は、「worker-0」、「worker-1」、「worker-2」などの名前の仮想スレッドを作成します。

ThreadFactory ファクトリー = Thread.ofVirtual().name("ワーカー", 0).factory();

次の例では、Executor API を使用して、タスクごとに新しい仮想スレッドを開始する ExecutorService を作成します。この例では、try-with-resources 構造を使用して、続行する前に ExecutorService が終了することを確認します。

ExecutorService はタスクを実行するための submit メソッドを定義します。submit メソッドはブロックしませんが、結果または例外を待つために使用できる Future オブジェクトを返します。タスクのコレクションを受け入れる Submit メソッドは、結果を表す完了した Future オブジェクトを遅延して入力する Stream を返します。

この例では、invokeAll および invokeAny コンビネーター メソッドを使用して複数のタスクを実行し、それらが完了するまで待機します。

try (ExecutorService executor = Executors.newVirtualThreadExecutor()) { 
      // 値を返すタスクを送信し、結果を待ちます
    Future<String> future = executor.submit(() -> "foo"); 
    文字列結果 = future.join(); 
    // 値を返す 2 つのタスクを送信して、タスクが完了すると完了した Future オブジェクトが
 
    遅延的に取り込まれる Stream を取得します。 // タスクが完了すると、完了した Future オブジェクト
    が格納されます。 Stream<Future<String>> stream = executor.submit(List.of(() -> "foo") 、() -> "バー")); 
    stream.filter(Future::isCompletedNormally) 
            .map(Future::join) 
            .forEach(System.out::println); 
    // 値を返す 2 つのタスクを実行し、両方が完了するのを待ちます
 
    List<Future<String>> results1 = executor.invokeAll(List.of(() -> "foo", () -> "bar")); 
 
    // 値を返す 2 つのタスクを実行し、両方が完了するのを待ちます。// タスクの 1 つが
    例外で完了すると、もう 1 つはキャンセルされます。
    List<Future<String>> results2 = executor.invokeAll(List.of(() -> "foo", () -> "bar"), /*waitAll*/ false); 
 
    // 値を返す 2 つのタスクを実行し、最初のタスクの結果を
    // 返して完了し、もう 1 つはキャンセルします。
    最初の文字列 = executor.invokeAny(List.of(() -> "foo", () -> "bar")); 

}

3. SpringBoot がコルーチンを使用する方法

1. プロジェクトルーム

Java Project Loom は、Java 仮想マシンの実行モデルを改善することを目的としています。その中心となる概念は、軽量スレッドとしても知られるファイバーです。Fibers は、従来のスレッドのように大量のシステム リソースを消費することなく、多数の同時タスクを効率的に作成および管理できる軽量のスレッド モデルを提供します。Spring Boot 自体は Project Loom を統合しませんが、Spring Boot アプリケーションで Project Loom を使用してコルーチンを実装できます。これを行うには、Java 17 以降を使用し、Project Loom を依存関係として含める必要があります。

以下は、Project Loom の Fibers を使用してコルーチンを実装する方法を示す簡単な例です。

public class CoroutineExample { 

    public static void main(String[] args) throws InterruptedException { 
        ExecutorService executorService = Executors.newVirtualThreadExecutor(); 

        SubmissionPublisher<String> Publisher = new SubmissionPublisher<>(executorService, 1); 

        // パブリッシャーをサブスクライブします
        publisher.subscribe(new SimpleSubscriber()); 
        // (int i = 0; i < 5; i++) { 
            publisher.submit("Data " + i);の

        データをパブリッシュします。
        } 
        // パブリッシャーを閉じ、サブスクライバーが終了するまで待ちます
        executorService.awaitTermination(1, TimeUnit.SECONDS);

        executorService.shutdown(); 
    } 
}

2. クエーサーフレームワーク

Quasar は、コルーチンの実装と管理を提供する Java ベースのコルーチン ライブラリです。Quasar を使用すると、Spring Boot アプリケーションでコルーチンを作成し、同時タスクを処理できます。

Quasar を使用するには、それを依存関係として Spring Boot プロジェクトに追加する必要があります。その後、Quasar が提供する API を使用して、コルーチンを作成、一時停止、再開できます。

以下は、Quasar を使用して Spring Boot アプリケーションにコルーチンを実装する方法を示す簡単な例です。

@FiberSpringBootApplication 
    public class CoroutineExample { 

        public static void main(String[] args) throws InterruptedException { 
            new Fiber<Void>(() -> { 
                for (int i = 0; i < 5; i++) { 
                    System.out.println( "データ " + i); 
                    try { 
                        Fiber.sleep(1000); 
                    } catch (SuspendExecution | InterruptedException e) { 
                        e.printStackTrace(); 
                    } 
                } 
            }).start().join(); 
        } 
    }

4. サードパーティの統合

4.1.Vert.x

Vert.x は、開発者が Java またはその他の JVM 言語を使用して高性能の非同期アプリケーションを作成できるようにするイベント駆動型のリアクティブ フレームワークです。Vert.x は Java 仮想スレッドの統合を試み始めており、現在、async/await 実装を含む仮想スレッド インキュベーター プロジェクトがあります。このプロジェクトを使用すると、開発者はコールバックや Future を使用せずに、JavaScript や C# に似た構文を使用して非同期コードを作成できます。

Vert.x は、応答性、パフォーマンス、スケーラブルなアプリケーションを構築するためのツールキットおよびフレームワークです。これは Java 言語に基づいており、開発者がイベント駆動型のノンブロッキング アプリケーションを簡単に構築できる非同期プログラミング モデルを提供します。

主な機能と利点:

  1. リアクティブかつノンブロッキング: Vert.x はイベント ループと非同期プログラミング モデルを採用しており、アプリケーションがリクエストとイベントをノンブロッキングで処理できるため、高スループットと低遅延が実現します。
  2. 多言語サポート: Vert.x は Java で構築されていますが、Kotlin、Groovy、JavaScript などの他の言語もサポートしています。これにより、開発者は好みの言語でアプリケーションを作成できるようになります。
  3. 組み込みのクラスター サポート: Vert.x には、複数のノードでアプリケーション インスタンスを実行するためのクラスター サポートが組み込まれており、水平スケーリングと高可用性が可能になります。
  4. 豊富なコンポーネント: Vert.x は、HTTP サーバー、WebSocket、メッセージ バス、データベース クライアントなどを含む豊富なコンポーネントとライブラリを提供し、開発者がさまざまな種類のアプリケーションを迅速に構築できるようにします。
  5. 軽量: Vert.x は軽量のフレームワークであり、一部の大規模なフレームワークほど肥大化しておらず、リソースが限られた環境でも実行できます。
  6. 活発なコミュニティ: Vert.x には、継続的な開発と更新を行う活発なオープンソース コミュニティがあり、テクノロジーの最先端を維持しており、それをサポートおよび拡張する多くの貢献者がいます。

Vert.x は、さまざまな種類のアプリケーション、特に高性能、高い同時実行性、およびリアルタイム パフォーマンスを必要とするアプリケーションの構築に適しています。Web アプリケーション、API サービス、リアルタイム通信アプリケーション、IoT アプリケーションなどの構築に使用できます。リアクティブ プログラミングとハイパフォーマンス アプリケーション開発に興味がある場合は、Vert.x をチェックしてみる価値があります。

4.2.桟橋

Jetty は、軽量の Java Web サーバーおよびサーブレット コンテナです。Jetty はすでに Java 仮想スレッドもサポートしています。

Java 19 で導入された仮想スレッドは、それぞれ 10.11.10 および 0.12.11 以降の Jetty 0 および Jetty 12 でサポートされていたため、Jetty 12 でもサポートされます。

JVM が仮想スレッドをサポートし、Jetty で有効になっている場合 (「組み込みの使用法」と「スタンドアロンの使用法」を参照)、アプリケーションは仮想スレッドを使用して呼び出されます。これにより、アプリケーションは単純なブロッキング API を使用できるようになりますが、仮想スレッドのスケーラビリティの利点も得られます。

4.3.トムキャット

Tomcat は、広く使用されている Java Web サーバーおよびサーブレット コンテナです。Tomcat は Java 仮想スレッドもサポートしており、このバージョンには関連する手順が含まれています。

4.4. ヘリドン

Helidon は、Helidon SE と Helidon MP という 2 つのプログラミング モデルを提供するマイクロサービス フレームワークです。Helidon SE は、Reactive Streams とノンブロッキング IO をサポートする関数型プログラミングに基づく軽量フレームワークです。Helidon MP は、MicroProfile API をサポートする標準化されたアノテーション駆動のフレームワークです。Helidon には Java 仮想スレッドも統合されており、その使用方法を示すサンプル コードがいくつか提供されています。

4.5.クォーカス

Quarkus は、クラウドネイティブ アプリケーション用のフルスタック フレームワークであり、高パフォーマンス、低メモリ フットプリント、高速起動、ホット リロードなどの機能を提供します。Quarkus はすでに Java 仮想スレッドもサポートしており、その使用方法に関するドキュメントとガイドを提供しています。


記事が役に立った場合は、注目といいねを歓迎します!

おすすめ

転載: blog.csdn.net/citywu123/article/details/132141035