Java : Future - API使用例
Future (Java SE 18 & JDK 18) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
Futureは、非同期計算の結果を表します。 計算が完了したかどうかのチェック、完了までの待機、計算結果の取得などを行うためのメソッドが用意されています。
Futureはインタフェースは、非同期処理の結果を表します。
- 処理が完了したかどうかのチェック
- 完了までの待機
- 結果の取得
などを行うためのメソッドが用意されています。
主に ExecutorService の submit メソッドの戻り値として取得して使います。
final var executorService = Executors.newSingleThreadExecutor();
try {
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("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
メソッド
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.");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} catch (InterruptedException e) {
System.out.println("Interrupted!");
return null;
} finally {
System.out.println("task end : " + getTime.getAsDouble() + " sec.");
}
});
TimeUnit.SECONDS.sleep(1);
// 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.");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} catch (InterruptedException e) {
System.out.println("Interrupted!");
return null;
} finally {
System.out.println("task end : " + getTime.getAsDouble() + " sec.");
}
});
TimeUnit.SECONDS.sleep(1);
// 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.");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} catch (InterruptedException e) {
System.out.println("Interrupted!");
return null;
} finally {
System.out.println("task end : " + getTime.getAsDouble() + " sec.");
}
});
// タスクが完了するのを待ちます。
TimeUnit.SECONDS.sleep(3);
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");
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("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");
TimeUnit.SECONDS.sleep(2);
throw new IllegalStateException("Exception!");
} 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("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");
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);
TimeUnit.SECONDS.sleep(1);
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");
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(3, TimeUnit.SECONDS);
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");
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);
System.out.println("-- get start --");
final var ret = future.get(1, TimeUnit.SECONDS);
// ↓ここは呼び出されません。
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");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} finally {
System.out.println("task end");
}
});
TimeUnit.SECONDS.sleep(1);
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");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} finally {
System.out.println("task end");
}
});
TimeUnit.SECONDS.sleep(1);
System.out.println("-- before cancel -- : " + future.isCancelled());
// タスクが完了するのを待ちます。
TimeUnit.SECONDS.sleep(2);
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");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} finally {
System.out.println("task end");
}
});
TimeUnit.SECONDS.sleep(1);
System.out.println("-- isDone 1 -- : " + future.isDone());
// タスクが完了するのを待ちます。
TimeUnit.SECONDS.sleep(2);
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");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} finally {
System.out.println("task end");
}
});
TimeUnit.SECONDS.sleep(1);
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