Java : Future - API使用例
Future (Java SE 19 & JDK 19) の使用例まとめです。
 だいたいのメソッドを網羅済みです。
 API仕様のおともにどうぞ。
概要
Futureは、非同期計算の結果を表します。 計算が完了したかどうかのチェック、完了までの待機、計算結果の取得などを行うためのメソッドが用意されています。
Futureはインタフェースは、非同期処理の結果を表します。
- 処理が完了したかどうかのチェック
 - 完了までの待機
 - 結果の取得
 
などを行うためのメソッドが用意されています。
主に ExecutorService の submit メソッドの戻り値として取得して使います。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.printf("task : start (%f sec.)%n", elapsedTime.getAsDouble());
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.printf("task : end (%f sec.)%n", elapsedTime.getAsDouble());
        }
    });
    TimeUnit.SECONDS.sleep(1);
    System.out.printf("future.get ... (%f sec.)%n", elapsedTime.getAsDouble());
    final var ret = future.get();
    System.out.printf("future.get OK! (%f sec.)%n", elapsedTime.getAsDouble());
    System.out.println("ret = " + ret);
}
// 結果
// ↓
//task : start (0.002537 sec.)
//future.get ... (1.003706 sec.)
//task : end (2.004116 sec.)
//future.get OK! (2.004768 sec.)
//ret = abcd
 
メソッド
boolean cancel (boolean mayInterruptIfRunning)
このタスクの実行の取消しを試みます。
// 基準となる時刻
final long current = System.nanoTime();
// 基準となる時刻からの差分を秒として取得
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
class Task implements Callable<String> {
    private final String name;
    Task(String name) {
        this.name = name;
    }
    @Override
    public String call() {
        try {
            System.out.printf("%s : task start (%f sec.)%n", name, elapsedTime.getAsDouble());
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.printf("%s : task end (%f sec.)%n", name, elapsedTime.getAsDouble());
        }
    }
}
try (final var executorService = Executors.newSingleThreadExecutor()) {
    System.out.println("submit A");
    final var futureA = executorService.submit(new Task("A"));
    TimeUnit.SECONDS.sleep(1);
    System.out.println("submit B");
    final var futureB = executorService.submit(new Task("B"));
    System.out.println("-- cancel tasks --");
    final var retA = futureA.cancel(false);
    System.out.printf("cancel A : ret = %b (%f sec.)%n", retA, elapsedTime.getAsDouble());
    final var retB = futureB.cancel(false);
    System.out.printf("cancel B : ret = %b (%f sec.)%n", retB, elapsedTime.getAsDouble());
}
System.out.println("-- end --");
// 結果
// ↓
//submit A
//A : task start (0.002960 sec.)
//submit B
//-- cancel tasks --
//cancel A : ret = true (1.014476 sec.)
//cancel B : ret = true (1.014648 sec.)
//A : task end (2.016125 sec.)
//-- end --
// ※mayInterruptIfRunning = false では割込みは発生しません。
//  また、サブミットだけで開始されていなかったタスクBは、開始されないまま終了します。
 
       final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.printf("task start (%f sec.)%n", elapsedTime.getAsDouble());
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.printf("task end (%f sec.)%n", elapsedTime.getAsDouble());
        }
    });
    TimeUnit.SECONDS.sleep(1);
    System.out.printf("cancel! (%f sec.)%n", elapsedTime.getAsDouble());
    final var ret = future.cancel(true);
    System.out.printf("cancel ret = %b%n", ret);
}
// 結果
// ↓
//task start (0.003275 sec.)
//cancel! (1.004838 sec.)
//Interrupted!
//task end (1.005646 sec.)
//cancel ret = true
// ※mayInterruptIfRunning = true は割込みを発生させます。
 
       final long current = System.nanoTime();
final DoubleSupplier elapsedTime = () -> (System.nanoTime() - current) / 1000000000.0;
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.printf("task start (%f sec.)%n", elapsedTime.getAsDouble());
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.printf("task end (%f sec.)%n", elapsedTime.getAsDouble());
        }
    });
    // タスクが完了するのを待ちます。
    System.out.println("get = " + future.get());
    final var ret = future.cancel(true);
    System.out.printf("cancel ret = %b (%f sec.)%n", ret, elapsedTime.getAsDouble());
}
// 結果
// ↓
//task start (0.002477 sec.)
//task end (2.009747 sec.)
//get = abcd
//cancel ret = false (2.011178 sec.)
// ※すでに終了しているタスクに対して cancel すると false を返します。
 
      default Throwable exceptionNow ()
待機せずにタスクによってスローされた例外を返します。
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var futures = new ArrayList<Future<String>>();
    futures.add(executorService.submit(() -> "abc"));
    futures.add(executorService.submit(() -> "XYZ"));
    futures.add(executorService.submit(() -> {
        throw new IllegalStateException("Fail!");
    }));
    futures.add(executorService.submit(() -> "1234"));
    final var results = futures.stream()
            .filter(f -> f.state() == Future.State.SUCCESS)
            .map(Future::resultNow)
            .toList();
    System.out.println("results = " + results);
    final var exceptions = futures.stream()
            .filter(f -> f.state() == Future.State.FAILED)
            .map(Future::exceptionNow)
            .toList();
    System.out.println("exceptions = " + exceptions);
}
// 結果
// ↓
//results = [abc, XYZ, 1234]
//exceptions = [java.lang.IllegalStateException: Fail!]
 
      V get ()
必要に応じて計算が完了するまで待機し、その後、計算結果を取得します。
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    System.out.println("-- get start --");
    final var ret = future.get();
    System.out.println("-- get end --");
    System.out.println("ret = " + ret);
}
// 結果
// ↓
//task start
//-- get start --
//task end
//-- get end --
//ret = abcd
 
       try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            TimeUnit.SECONDS.sleep(2);
            throw new IllegalStateException("Fail!");
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    try {
        System.out.println("-- get start --");
        final var ret = future.get();
        System.out.println("-- get end --");
        System.out.println("ret = " + ret);
    } catch (ExecutionException e) {
        System.out.println("ExecutionException! : " + e.getMessage());
    }
}
// 結果
// ↓
//task start
//-- get start --
//task end
//ExecutionException! : java.lang.IllegalStateException: Fail!
 
       try (final var executorService = Executors.newScheduledThreadPool(2)) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            TimeUnit.SECONDS.sleep(3);
            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);
    }, 2, TimeUnit.SECONDS);
    try {
        System.out.println("-- get start --");
        final var ret = future.get();
        System.out.println("-- get end --");
        System.out.println("ret = " + ret);
    } catch (CancellationException e) {
        System.out.println("CancellationException!");
    }
}
// 結果
// ↓
//task start
//-- get start --
//future.cancel
//Interrupted!
//CancellationException!
//task end
 
      V get (long timeout, TimeUnit unit)
必要に応じて、最大で指定された時間、計算が完了するまで待機し、その後、計算結果が利用可能な場合は結果を取得します。
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    try {
        System.out.println("-- get start --");
        final var ret = future.get(3, TimeUnit.SECONDS);
        System.out.println("-- get end --");
        System.out.println("ret = " + ret);
    } catch (TimeoutException e) {
        System.out.println("TimeoutException!");
    }
}
// 結果
// ↓
//task start
//-- get start --
//task end
//-- get end --
//ret = abcd
 
       try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("task start");
            TimeUnit.SECONDS.sleep(3);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("task end");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    try {
        System.out.println("-- get start --");
        final var ret = future.get(1, TimeUnit.SECONDS);
        System.out.println("-- get end --");
        System.out.println("ret = " + ret);
    } catch (TimeoutException e) {
        System.out.println("TimeoutException!");
    }
}
// 結果
// ↓
//task start
//-- get start --
//TimeoutException!
//task end
 
      boolean isCancelled ()
このタスクが正常に完了する前に取り消された場合はtrueを返します。
try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("-- task start --");
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("-- task end --");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    System.out.println("isCancelled = " + future.isCancelled());
    System.out.println("isDone = " + future.isDone());
    System.out.println("state = " + future.state());
    // タスクが完了するのを待ちます。
    System.out.println("get = " + future.get());
    System.out.println("isCancelled = " + future.isCancelled());
    System.out.println("isDone = " + future.isDone());
    System.out.println("state = " + future.state());
    // タスク完了後にキャンセルしても isCancelled は true になりません。
    System.out.println("----");
    System.out.println("cancel = " + future.cancel(false));
    System.out.println("isCancelled = " + future.isCancelled());
}
// 結果
// ↓
//-- task start --
//isCancelled = false
//isDone = false
//state = RUNNING
//-- task end --
//isCancelled = false
//isDone = true
//state = SUCCESS
//----
//cancel = false
//isCancelled = false
 
       try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("-- task start --");
            TimeUnit.SECONDS.sleep(2);
            return "abcd";
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("-- task end --");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    System.out.println("isCancelled = " + future.isCancelled());
    System.out.println("isDone = " + future.isDone());
    System.out.println("state = " + future.state());
    System.out.println("----");
    System.out.println("cancel = " + future.cancel(false));
    System.out.println("isCancelled = " + future.isCancelled());
    System.out.println("isDone = " + future.isDone());
    System.out.println("state = " + future.state());
}
// 結果
// ↓
//-- task start --
//isCancelled = false
//isDone = false
//state = RUNNING
//----
//cancel = true
//isCancelled = true
//isDone = true
//state = CANCELLED
//-- task end --
 
       try (final var executorService = Executors.newSingleThreadExecutor()) {
    final var future = executorService.submit(() -> {
        try {
            System.out.println("-- task start --");
            TimeUnit.SECONDS.sleep(2);
            throw new IllegalStateException("Fail!");
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
            return null;
        } finally {
            System.out.println("-- task end --");
        }
    });
    TimeUnit.SECONDS.sleep(1);
    System.out.println("isCancelled = " + future.isCancelled());
    System.out.println("isDone = " + future.isDone());
    System.out.println("state = " + future.state());
    try {
        System.out.println("get = " + future.get());
    } catch (ExecutionException e) {
        System.out.println("ExecutionException! : " + e.getMessage());
    }
    System.out.println("isCancelled = " + future.isCancelled());
    System.out.println("isDone = " + future.isDone());
    System.out.println("state = " + future.state());
}
// 結果
// ↓
//-- task start --
//isCancelled = false
//isDone = false
//state = RUNNING
//-- task end --
//ExecutionException! : java.lang.IllegalStateException: Fail!
//isCancelled = false
//isDone = true
//state = FAILED
 
      boolean isDone ()
このタスクが完了した場合はtrueを返します。
このメソッドの使用例は、isCancelled() にまとめて記載しました。
 そちらのAPI使用例をご参照ください。
default V resultNow ()
計算された結果を待たずに返します。
このメソッドの使用例は、exceptionNow() にまとめて記載しました。
 そちらのAPI使用例をご参照ください。
default Future.State state ()
計算状態を返します。
このメソッドの使用例は、isCancelled() にまとめて記載しました。
 そちらのAPI使用例をご参照ください。
関連記事
- API 使用例 
        
- BlockingQueue (ブロッキング・キュー)
 - BrokenBarrierException
 - Callable
 - CancellationException
 - ConcurrentHashMap.KeySetView (並列処理用セット)
 - ConcurrentLinkedDeque (並列処理用・両端キュー)
 - ConcurrentLinkedQueue (並列処理用キュー)
 - ConcurrentMap (並列処理用マップ)
 - ConcurrentModificationException (並列処理例外)
 - ConcurrentSkipListSet (並列処理用セット)
 - Condition (同期)
 - CopyOnWriteArrayList (並列処理用リスト)
 - CopyOnWriteArraySet (並列処理用セット)
 - CountDownLatch (同期)
 - CyclicBarrier (同期)
 - Exchanger (同期)
 - ExecutionException
 - Executor
 - ExecutorService
 - Executors
 - Future.State
 - FutureTask
 - InterruptedException (割込み例外)
 - Lock (同期)
 - Object (オブジェクト)
 - Runnable
 - Semaphore (セマフォ)
 - Thread (スレッド)
 - ThreadGroup
 - ThreadLocal
 - TimeoutException
 - TimeUnit
 
 



