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

Java 9のCompletableFuture#delayedExecutor()メソッドとは?使い方と活用場面を解説

Java 9では、CompletableFutureクラスにdelayedExecutor()メソッドが新たに追加されました。このメソッドを利用すると、指定した時間だけ処理を遅らせてからタスクを実行するExecutorを簡単に作成できます。リトライ処理や遅延実行が必要な非同期処理において非常に便利な機能です。

delayedExecutor()には、2つのオーバーロードされたメソッドが定義されています。

  • 1つ目のメソッド: CompletableFutureがデフォルトで使用するExecutorオブジェクトをもとに、指定した遅延時間の経過後にタスクを実行する新しいExecutorオブジェクトを返します。
  • 2つ目のメソッド: 同様にExecutorオブジェクトを返しますが、こちらは呼び出し側が引数として渡した独自のExecutorオブジェクトを使用して、遅延後にタスクを実行します。

構文

public static Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
public static Executor delayedExecutor(long delay, TimeUnit unit)
  • delay: 遅延させる時間(数値)
  • unit: 遅延時間の単位(TimeUnit.SECONDS など)
  • executor: 遅延後にタスクを実行する基となるExecutor(省略可能)

コード例

次のサンプルでは、completeAsync()と組み合わせてdelayedExecutor()を使用し、3秒遅延させてから非同期タスクを実行しています。メインスレッドは1秒ごとにカウントを出力しながら動作を続けます。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class DelayedExecutorMethodTest {
    public static void main(String args[]) throws InterruptedException, ExecutionException {
        CompletableFuture<String> future = new CompletableFuture<>();
        future.completeAsync(() -> {
            try {
                System.out.println("inside future: processing data...");
                return "tutorialspoint.com";
            } catch(Throwable e) {
                return "not detected";
            }
        }, CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS))
                .thenAccept(result -> System.out.println("accept: " + result));
        for(int i = 1; i <= 5; i++) {
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("running outside... " + i + " s");
        }
    }
}

実行結果

running outside... 1 s
running outside... 2 s
inside future: processing data...
accept: tutorialspoint.com
running outside... 3 s
running outside... 4 s
running outside... 5 s

実行結果のポイント

出力を見ると、メインスレッドは1秒ごとに「running outside...」を出力しています。一方、delayedExecutor(3, TimeUnit.SECONDS)によって遅延が設定されたため、非同期タスクは開始から約3秒後に実行され、「inside future: processing data...」と「accept: tutorialspoint.com」が出力されていることがわかります。このように、メインスレッドの処理をブロックすることなく、指定したタイミングで非同期処理を実行できます。

どんな場面で使うべきか

delayedExecutor()が特に役立つのは、以下のようなケースです。

  • リトライ処理: 失敗したAPI呼び出しなどを、一定時間待ってから再実行したい場合
  • 遅延初期化: アプリ起動直後ではなく、少し時間を置いてからバックグラウンド処理を開始したい場合
  • タイムアウト制御: 一定時間内に応答がなければ別処理へ切り替えるような制御を実装したい場合

従来はScheduledExecutorServiceを自前で用意する必要がありましたが、Java 9以降はdelayedExecutor()を使うことで、CompletableFutureの非同期チェーンの中に自然な形で遅延実行を組み込めるようになりました。

  1. Javaのpack()メソッドとは?使い方とsetSize()との違いを解説

    pack()メソッドは、JavaのWindowクラスで定義されているメソッドで、フレーム内のすべてのコンポーネントがそれぞれの推奨サイズ(preferred size)以上で表示されるように、ウィンドウのサイズを自動的に調整します。 代替手段として、setSize()メソッドやsetBounds()メソッドを呼び出して、フレームのサイズを明示的に指定する方法もあります。しかし一般的には、pack()メソッドを使用する方がsetSize()よりも推奨されています。その理由は、pack()がフレームのサイズ決定をレイアウトマネージャーに委ねることができ、レイアウトマネージャーはプラットフォーム間の

  2. JavaのsetBounds()メソッドとは?使い方とサンプルコードを解説

    JavaのGUIプログラミングでは、レイアウトマネージャー(Layout Manager)がコンポーネントの位置やサイズを自動的に決定します。しかし、レイアウトマネージャーを使用しない場合は、コンポーネントの位置とサイズを手動で設定する必要があります。そのような場面で活躍するのがsetBounds()メソッドです。フレームのレイアウトマネージャーをnullに設定することで、コンポーネントの位置とサイズを自由に指定できるようになります。setBounds()メソッドの基本setBounds()メソッドは4つの引数を取ります。第1引数と第2引数はコンポーネントの左上隅のx座標・y座標、第3引数はコ