0Pricing
Java Academy · レッスン

仮想スレッドの作成

Thread.ofVirtual とエグゼキューターです。

「仮想スレッドの作成」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

仮想スレッドの作成方法

Java には、仮想スレッドを作成するためのエントリーポイントがいくつか用意されています。特に重要なのは、Thread.ofVirtual() ビルダーと Executors.newVirtualThreadPerTaskExecutor() ファクトリです。

このレッスンでは、それぞれの使い方を説明します。

ビルダー: start

Thread.ofVirtual() はビルダーを返します。.start(runnable) を呼び出すと、スレッドが作成され、すぐに開始されます。

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = Thread.ofVirtual().start(() ->
            System.out.println("Started directly"));
        t.join();
    }
}

ビルダー: unstarted

スレッドを設定してから後で開始したい場合は、.unstarted(runnable) を使用します。

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = Thread.ofVirtual().unstarted(() ->
            System.out.println("Started later"));
        System.out.println("Before start, alive? " + t.isAlive());
        t.start();
        t.join();
    }
}

再利用可能なファクトリ

ビルダーの .factory() を使うと、ThreadFactory を生成できます。newThread を呼び出すたびに、新しい仮想スレッドが生成されます。

import java.util.concurrent.ThreadFactory;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ThreadFactory factory = Thread.ofVirtual().name("job-", 0).factory();
        Thread a = factory.newThread(() ->
            System.out.println(Thread.currentThread().getName()));
        Thread b = factory.newThread(() ->
            System.out.println(Thread.currentThread().getName()));
        a.start(); b.start();
        a.join(); b.join();
    }
}

便利なメソッド

Thread.startVirtualThread(runnable) は、名前のない仮想スレッドを1回の呼び出しで作成して開始するための短縮記法です。

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = Thread.startVirtualThread(() ->
            System.out.println("One-liner virtual thread"));
        t.join();
    }
}

エグゼキュータを使う方法

タスク指向のコードでは、Executors.newVirtualThreadPerTaskExecutor() を使用するのがおすすめです。これは、送信されたすべてのタスクに対して新しい仮想スレッドを作成します。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            exec.submit(() -> System.out.println("task one"));
            exec.submit(() -> System.out.println("task two"));
        }
        System.out.println("All tasks submitted and completed");
    }
}

try-with-resources を使う理由

Java 19 以降、ExecutorService は AutoCloseable を実装しています。try-with-resources ブロック内で閉じると、送信済みのすべてのタスクが完了するまで待機します。

これにより、手動で shutdown や awaitTermination を呼び出さなくても、クリーンで構造化されたシャットダウンを実現できます。

大量のタスクを送信する

タスクごとのエグゼキュータは、膨大な数のタスクを簡単に処理できます。各タスクには専用の仮想スレッドが割り当てられます。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    public static void main(String[] args) {
        AtomicInteger sum = new AtomicInteger();
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            for (int i = 1; i <= 1000; i++) {
                final int n = i;
                exec.submit(() -> sum.addAndGet(n));
            }
        }
        System.out.println("Sum 1..1000 = " + sum.get());
    }
}

Future で結果を収集する

submit は Future を返すため、ほかのエグゼキュータと同じように戻り値を収集できます。

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws Exception {
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            Future<Integer> f = exec.submit(() -> 6 * 7);
            System.out.println("Result: " + f.get());
        }
    }
}

ビルダーとエグゼキュータ

目的に応じて選択します。

  • 単発のスレッドやカスタム名が必要な場合は、Builder / startVirtualThread
  • タスクのコレクションを送信して結果を収集する場合は、newVirtualThreadPerTaskExecutor

どちらも作業単位ごとに1つの仮想スレッドを作成します。これはまさに望ましい動作です。

仮想エグゼキュータをキャッシュしない

単一の仮想スレッドエグゼキュータを、固定数のワーカーを持つプールのように再利用しないでください。エグゼキュータ自体は再利用して構いませんが、各タスクによってまったく新しいスレッドが生成されることを覚えておいてください。

重要なのは、スレッドをプールするのではなく、タスクを便利に送信しているだけだという点です。

理解度チェック

それぞれが専用の仮想スレッドで実行される大量のタスクを処理する最適な方法を選んでください。

復習

仮想スレッドの作成方法を理解しました。

  • Thread.ofVirtual().start(...) と .unstarted(...)
  • 1行で書ける Thread.startVirtualThread(...)
  • 再利用可能な ThreadFactory を作成する .factory()
  • try-with-resources と組み合わせる Executors.newVirtualThreadPerTaskExecutor()

次は、プラットフォームスレッドと仮想スレッドのどちらを選ぶかを学びます。

よくある質問

「仮想スレッドの作成」レッスンは無料ですか?

はい。「仮想スレッドの作成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「仮想スレッドの作成」で何を学びますか?

Thread.ofVirtual とエグゼキューターです。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「仮想スレッドの作成」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 仮想スレッドとは
  2. 仮想スレッドの作成
  3. プラットフォームスレッドと仮想スレッド
  4. 落とし穴:ピン留めと ThreadLocal
← Java Academyに戻る