Java
 Computer >> コンピューター >  >> プログラミング >> Java

ScheduledThreadPoolとSingleThreadExecutorの違いとは?比較表とコード例で徹底解説

Javaの並行処理において、ScheduledThreadPool(スケジュール済みスレッドプール)とSingleThreadExecutor(シングルスレッドエグゼキュータ)は、どちらもExecutorsファクトリクラスから生成できる代表的なスレッドプールです。名前は似ていますが、その設計思想や内部動作、適したユースケースは大きく異なります。本記事では、両者の違いを比較表と実際のコード例を交えてわかりやすく解説します。

ScheduledThreadPoolとSingleThreadExecutorの違い一覧

No.項目ScheduledThreadPoolSingleThreadExecutor
1基本動作指定した遅延時間の経過後にタスクを実行したり、一定間隔で定期的に繰り返し実行したりできるスレッドプールを生成します。タスクは必ず投入された順番に実行され、同時にアクティブになるタスクは常に1つだけであることが保証されます。
2キューDelayQueue(遅延キュー)を使用し、時間的な遅延に基づいてタスクをスケジューリングします。ブロッキングキュー(BlockingQueue)を使用してタスクを管理します。
3スレッドの生存期間アイドル状態であっても、生成時に指定した数のコアスレッドがプール内に維持され続けます。タスクの実行中にスレッドが異常終了した場合でも、新しいスレッドが自動的に再生成され、処理が継続されます。
4スレッドプールサイズ生成時に指定した固定サイズのスレッドプールを持ちます。常に1つのスレッドのみで動作します。
5主なユースケース同時に実行するタスク数を制限したい場合や、遅延実行・定期実行が必要なバッチ処理に適しています。Task1がTask2より必ず先に実行されるようにしたいなど、タスクの実行順序を厳密に保証したい場合に適しています。

ScheduledThreadPoolの使用例

以下の例では、10個のスレッドを持つスケジュール済みスレッドプールを作成し、10秒後の一回限りの実行と、15秒後に開始して以降10秒間隔での定期実行を登録しています。

public class ScheduledThreadPoolExample {
    public static void main(String args[]) {
        ScheduledExecutorService services = Executors.newScheduledThreadPool(10);
        // 10秒後に一度だけタスクを実行
        services.schedule(new Task(), 10, TimeUnit.SECONDS);
        // 15秒後に初回実行し、以降は10秒間隔で繰り返し実行
        services.scheduleAtFixedRate(new Task(), 15, 10, TimeUnit.SECONDS);
    }
}

public class Task implements Runnable {
    @Override
    public void run() {
        System.out.println("In Run");
    }
}

SingleThreadExecutorの使用例

以下の例では、単一スレッドのエグゼキュータを作成し、タスクを送信(submit)しています。複数のタスクを投入しても、それらは必ず1つずつ順番に処理されます。

public class Main {
    public static void main(String args[]) {
        ExecutorService services = Executors.newSingleThreadExecutor();
        Future<?> future = services.submit(new Task());
    }
}

public class Task implements Runnable {
    @Override
    public void run() {
        System.out.println("In Run");
    }
}

まとめ:使い分けのポイント

ScheduledThreadPoolは、タイマー処理や定期バッチのように「いつ実行するか」を制御したい場面に最適です。一方、SingleThreadExecutorは、ログ出力やイベント処理のように、複数のタスクを決められた順序で確実に1つずつ処理したい場面で威力を発揮します。アプリケーションの要件に応じて適切なエグゼキュータを選択することで、安全かつ効率的な並行処理を実現できます。

  1. JavaにおけるThreadとRunnableの違いを徹底解説!使い分けのポイント

    Javaで新しいスレッドを作成する方法は主に2つあります。1つ目はThreadクラスを継承(extends)する方法、2つ目はRunnableインターフェースを実装(implements)する方法です。それぞれの特徴と違いを理解することで、状況に応じた適切な選択ができるようになります。 スレッド作成の2つの方法 1. Threadクラスを継承する方法 Threadクラスのサブクラスとして新しいクラスを宣言し、そのサブクラス内でrun()メソッドをオーバーライドします。その後、サブクラスのインスタンスを生成し、start()メソッドを呼び出すことでスレッドが実行されます。 2. Runna

  2. Javaにおける例外(Exception)とエラー(Error)の違いを徹底解説

    Javaにおいて、例外(Exception)とエラー(Error)はどちらも Throwable クラスのサブクラスです。しかし、両者には明確な違いがあり、堅牢なアプリケーションを開発するうえで、それぞれの特性を正しく理解することは非常に重要です。 エラー(Error)とは エラーは、主にシステムリソースの不足によって発生する深刻な問題を示します。この種の問題はアプリケーション側でキャッチ(捕捉)すべきものではなく、基本的にプログラマーが対処できる範囲を超えています。代表的な例としては、システムクラッシュやメモリ不足(OutOfMemoryError)などが挙げられます。 エラーはほとんどの