Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JJUGナイトセミナー「Java 26 リリース記念イベント」 - JEP525

Avatar for raedion raedion
March 24, 2026
14

JJUGナイトセミナー「Java 26 リリース記念イベント」 - JEP525

Avatar for raedion

raedion

March 24, 2026

Transcript

  1. JEP 525: Structured Concurrency (Sixth Preview) — Java 26 JJUG

    ナイトセミナー 2026/03/24 Kanta Koto
  2. 自己紹介 名前: 古藤 寛大(Kanta Koto ) 所属: 株式会社野村総合研究所 普段の仕事: OSS

    サポート業務(ex. Keycloak 、WildFly 、Spring 関連など) Twitter/X: @kotkanri 2
  3. Structured Concurrency の概要 Structured Concurrency (構造化並行処理) の API 異なるスレッドで実行される関連タスク群を 1

    つの作業単位 として扱う スレッド間の関係性が明確になるよう、ソースコード上で「構造化」している サブタスクのライフサイクルが親のコードブロックのスコープ範囲に制限できる ため、スレッドリークやキャンセル漏れを構造的に防げる 大量に生成されるVirtualThread をトレースしやすい メリット:エラーハンドリング・キャンセルがシンプルに java.util.concurrent.StructuredTaskScope 3
  4. 従来の方法だと、スレッドリーク・キャンセル漏れのリスクがある Response handle() throws ExecutionException, InterruptedException { Future<String> user =

    executor.submit(() -> findUser()); Future<Integer> order = executor.submit(() -> fetchOrder()); String theUser = user.get(); // fetchOrder失敗時もブロック int theOrder = order.get(); return new Response(theUser, theOrder); } タスク同士の関係がコード上で保障されておらず、片方が処理に失敗してももう片方が動 き続けたり待ち続ける → スレッドリーク ExecutorService の cancel メソッドを使う手段もあるが、実装が煩雑になりがち 4
  5. Structured Concurrency を利用すると、構造的にタスクの安全性を担 保できる Response handle() throws InterruptedException { try

    (var scope = StructuredTaskScope.open()) { Subtask<String> user = scope.fork(() -> findUser()); Subtask<Integer> order = scope.fork(() -> fetchOrder()); scope.join(); return new Response(user.get(), order.get()); } } 5
  6. 具体的には以下のような処理の仕組みとなっている Response handle() throws InterruptedException { // 関連タスクが実行される範囲をコードブロックで明確に定義 try (var

    scope = StructuredTaskScope.open()) { // 1つ目のサブタスクを実行 Subtask<String> user = scope.fork(() -> findUser()); // 2つ目のサブタスクを実行 Subtask<Integer> order = scope.fork(() -> fetchOrder()); // 全サブタスク完了まで待機 scope.join(); // 両方成功 → 結果を合成 return new Response(user.get(), order.get()); } // スコープ終了時、全サブタスクの終了が保証される } 処理フロー: open() → fork() → join() → 結果取得 → close() 6
  7. Structured Concurrency のこれまでのリリース履歴 JDK JEP ステータス 19 428 Incubator (1st)

    20 437 Incubator (2nd) 21 453 Preview (1st) — fork() が Subtask を返すように 22 462 Preview (2nd) — 変更なし 23 480 Preview (3rd) — 変更なし 24 499 Preview (4th) — open() ファクトリメソッド、 Joiner API 25 505 Preview (5th) — 設定API 改良 26 525 Preview (6th) ← 今回 7
  8. JDK25 (JEP505 )からJDK26 (JEP525 )の変更点 変更内容 JEP 505 (5th) JEP

    525 (6th) Joiner にタイムアウトハンドリング なし onTimeout() メソッド追加 全成功時の結果型 Stream<Subtask<T>> List<T> 任意1 つ成功のメソッド名 anySuccessfulResultOrThrow() anySuccessfulOrThrow() open() の設定パラメータ Function UnaryOperator 8
  9. ( 付録) コンパイル・実行方法 # javac + java javac --release 26

    --enable-preview Main.java java --enable-preview Main # ソースコードランチャー(単一ファイル) java --enable-preview Main.java # jshell で試す jshell --enable-preview --enable-preview が必須(プレビューAPI のため) 9
  10. まとめ JEP 525 = Structured Concurrency の 6 回目のプレビュー (Java

    26) JEP 505 からの変更は マイナーだが実用的な改善 onTimeout() / List 戻り値 / メソッドリネーム / UnaryOperator 正式化は間近 — 今のうちに API を触っておこう --enable-preview で 今日から試せる 押さえておくべきこと open() → fork() → join() → close() の処理フロー Virtual Threads との組み合わせが鍵 10