在以下代码中,其目的是实现任务的异步执行,前提是该任务在少于100毫秒内运行,否则将引发其他线程的超时异常,
问题:异步执行100毫秒以上的线程会发生什么情况,它会被释放吗?还是会等待任务完成而不会抛出异常? (编写代码时认为acceptEither一旦遇到另一个将来发生的timeOutException就会终止长期运行的任务)
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static <T> CompletableFuture<T> failAfter(long longValue) {
final CompletableFuture<T> timeoutFuture = new CompletableFuture<>();
scheduler.schedule(() -> {
final TimeoutException ex = new TimeoutException("Timing out");
return timeoutFuture.completeExceptionally(ex);
}, longValue, TimeUnit.MILLISECONDS);
return timeoutFuture;
}
final CompletableFuture<CustomResponse> CustomResponseFuture = CompletableFuture.supplyAsync(() -> object.taks()).
exceptionally(ex -> {
System.out.println("help");
return new "Hello";
});
CustomResponseFuture
.acceptEither(failAfter(100l), TesFutureStuff::myNewMethod)
.exceptionally(throwable -> {
System.out.println("failure "+throwable.getMessage());
return null;
})/*.getNow(null )*/;
答案 0 :(得分:1)
如果只希望任务在特定时间后终止,则不需要CompletableFuture。只需create an ExecutorService,然后调用其invokeAny方法即可。
如果您坚持使用CompletableFuture,则可以使用其get和cancel方法:
CompletableFuture<CustomResponse> future = CompletableFuture.supplyAsync(() -> object.task());
try {
CustomResponse response = future.get(100, TimeUnit.MILLISECONDS);
// process response here
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
System.out.println(e);
future.cancel(true);
}
更新:
要在后台完成整个操作,请将invokeAny调用提交到同一ExecutorService,但要确保ExecutorService不是单线程的。有很多选择:Executors.newFixedThreadPool(2),Executors.newWorkStealingPool(),Executors.newCachedThreadPool甚至是ForkJoinPool.commonPool()。
对于CompletableFuture方法,我刚刚注意到,从Java 9开始,CompletableFuture添加了一个orTimeout方法:
future.orTimeout(100, TimeUnit.MILLISECONDS);
答案 1 :(得分:0)
CompletableFuture.supplyAsync(() -> execute(task), executorService)
.acceptEither(new CompletableFuture()
.completeExceptionally( new RuntimeException(String.format("timed out %d %s",timeout, unit.name()))), result ->onSuccess(task,result))
.exceptionally(throwable -> onError(task));