CompletableFuture长时间运行的任务超时,它会保留由超时将来组成的给定线程吗?

时间:2018-07-27 17:30:11

标签: java asynchronous java-8 completable-future

在以下代码中,其目的是实现任务的异步执行,前提是该任务在少于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 )*/;

2 个答案:

答案 0 :(得分:1)

如果只希望任务在特定时间后终止,则不需要CompletableFuture。只需create an ExecutorService,然后调用其invokeAny方法即可。

如果您坚持使用CompletableFuture,则可以使用其getcancel方法:

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));