Java : Future - API使用例

Future (Java SE 17 & JDK 17) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。


概要

クラス構成

Futureはインタフェースは、非同期処理の結果を表します。

  • 処理が完了したかどうかのチェック
  • 完了までの待機
  • 結果の取得

などを行うためのメソッドが用意されています。

主に ExecutorServicesubmit メソッドの戻り値として取得して使います。

メソッド

boolean cancel (boolean mayInterruptIfRunning)

このタスクの実行の取消しを試みます。

// 基準となる時刻
final long current = System.nanoTime();

// 基準となる時刻からの差分を秒として取得
final DoubleSupplier getTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start : " + getTime.getAsDouble() + " sec.");
            Thread.sleep(2000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end : " + getTime.getAsDouble() + " sec.");
        }
    });

    Thread.sleep(1000);

    // mayInterruptIfRunning = false
    final var ret = future.cancel(false);
    System.out.println("cancel = " + ret + " : " + getTime.getAsDouble() + " sec.");

} finally {
    executorService.shutdown();
    System.out.println("shutdown : " + getTime.getAsDouble() + " sec.");
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term = " + ret + " : " + getTime.getAsDouble() + " sec.");

// 結果
// ↓
//task start : 0.0030879 sec.
//cancel = true : 1.0165037 sec.
//shutdown : 1.0204428 sec.
//task end : 2.0135346 sec.
//term = true : 2.0140798 sec.

// ※mayInterruptIfRunning = false では割込みは発生しません。
final long current = System.nanoTime();
final DoubleSupplier getTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start : " + getTime.getAsDouble() + " sec.");
            Thread.sleep(2000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end : " + getTime.getAsDouble() + " sec.");
        }
    });

    Thread.sleep(1000);

    // mayInterruptIfRunning = true
    final var ret = future.cancel(true);
    System.out.println("cancel = " + ret + " : " + getTime.getAsDouble() + " sec.");

} finally {
    executorService.shutdown();
    System.out.println("shutdown : " + getTime.getAsDouble() + " sec.");
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term = " + ret + " : " + getTime.getAsDouble() + " sec.");

// 結果
// ↓
//task start : 0.0035929 sec.
//Interrupted!
//task end : 1.0059904 sec.
//cancel = true : 1.005947 sec.
//shutdown : 1.0097252 sec.
//term = true : 1.0098963 sec.

// ※mayInterruptIfRunning = true は割込みを発生させます。
final long current = System.nanoTime();
final DoubleSupplier getTime = () -> (System.nanoTime() - current) / 1000000000.0;

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start : " + getTime.getAsDouble() + " sec.");
            Thread.sleep(2000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end : " + getTime.getAsDouble() + " sec.");
        }
    });

    // タスクが完了するのを待ちます。
    Thread.sleep(3000);

    final var ret = future.cancel(true);
    System.out.println("cancel = " + ret + " : " + getTime.getAsDouble() + " sec.");

} finally {
    executorService.shutdown();
    System.out.println("shutdown : " + getTime.getAsDouble() + " sec.");
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term = " + ret + " : " + getTime.getAsDouble() + " sec.");

// 結果
// ↓
//task start : 0.0022581 sec.
//task end : 2.0066302 sec.
//cancel = false : 3.0161829 sec.
//shutdown : 3.0202056 sec.
//term = true : 3.0203844 sec.

// ※すでに終了しているタスクに対してcancelするとfalseを返します。

V get ()

必要に応じて計算が完了するまで待機し、その後、計算結果を取得します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- get start --");

    final var ret = future.get();

    System.out.println("-- get end --");
    System.out.println("future ret : " + ret);

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- get start --
//task end
//-- get end --
//future ret : abcd
//term : true
final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);

            throw new IllegalStateException("Exception!");

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- get start --");

    final var ret = future.get();

    System.out.println("-- get end --");
    System.out.println("future ret : " + ret);

} catch (ExecutionException e) {
    System.out.println("ExecutionException! : " + e.getMessage());
} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- get start --
//task end
//ExecutionException! : java.lang.IllegalStateException: Exception!
//term : true
final var executorService = Executors.newScheduledThreadPool(2);
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(3000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });

    // 2秒後にキャンセルします。
    executorService.schedule(() -> {
        System.out.println("future cancel");
        future.cancel(true);
    }, 2000, TimeUnit.MILLISECONDS);

    Thread.sleep(1000);

    System.out.println("-- get start --");

    final var ret = future.get();

    System.out.println("-- get end --");
    System.out.println("future ret : " + ret);

} catch (CancellationException e) {
    System.out.println("CancellationException!");
} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- get start --
//future cancel
//Interrupted!
//task end
//CancellationException!
//term : true

V get (long timeout, TimeUnit unit)

必要に応じて、最大で指定された時間、計算が完了するまで待機し、その後、計算結果が利用可能な場合は結果を取得します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- get start --");

    final var ret = future.get(3000, TimeUnit.MILLISECONDS);

    System.out.println("-- get end --");
    System.out.println("future ret : " + ret);

} catch (TimeoutException e) {
    System.out.println("TimeoutException!");
} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- get start --
//task end
//-- get end --
//future ret : abcd
//term : true
final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(3000);

            return "abcd";

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- get start --");

    final var ret = future.get(1000, TimeUnit.MILLISECONDS);

    // ↓ここは呼び出されません。
    System.out.println("-- get end --");
    System.out.println("future ret : " + ret);

} catch (TimeoutException e) {
    System.out.println("TimeoutException!");
} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- get start --
//TimeoutException!
//task end
//term : true

boolean isCancelled ()

このタスクが正常に完了する前に取り消された場合はtrueを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);
            return "abcd";
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- before cancel -- : " + future.isCancelled());

    future.cancel(false);

    System.out.println("-- after cancel -- : " + future.isCancelled());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- before cancel -- : false
//-- after cancel -- : true
//task end
//term : true
final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);
            return "abcd";
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- before cancel -- : " + future.isCancelled());

    // タスクが完了するのを待ちます。
    Thread.sleep(2000);

    future.cancel(false);

    // タスクの完了後にキャンセルをしても、isCancelledはtrueになりません。
    System.out.println("-- after cancel -- : " + future.isCancelled());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- before cancel -- : false
//task end
//-- after cancel -- : false
//term : true

boolean isDone ()

このタスクが完了した場合はtrueを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);
            return "abcd";
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- isDone 1 -- : " + future.isDone());

    // タスクが完了するのを待ちます。
    Thread.sleep(2000);

    System.out.println("-- isDone 2 -- : " + future.isDone());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- isDone 1 -- : false
//task end
//-- isDone 2 -- : true
//term : true
final var executorService = Executors.newSingleThreadExecutor();
try {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);
            return "abcd";
        } finally {
            System.out.println("task end");
        }
    });

    Thread.sleep(1000);

    System.out.println("-- isDone 1 -- : " + future.isDone());

    future.cancel(false);

    // タスクが終了していなくても、キャンセルされた直後にDoneとなります。
    System.out.println("-- isDone 2 -- : " + future.isDone());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- isDone 1 -- : false
//-- isDone 2 -- : true
//task end
//term : true

関連記事

ページの先頭へ