How to interrupt underlying execution of CompletableFuture

前端 未结 4 1609
自闭症患者
自闭症患者 2020-12-29 05:04

I know that CompletableFuture design does not control its execution with interruptions, but I suppose some of you might have this problem. CompletableFutu

4条回答
  •  自闭症患者
    2020-12-29 05:10

    What about?

    /** @return {@link CompletableFuture} which when cancelled will interrupt the supplier
     */
    public static  CompletableFuture supplyAsyncInterruptibly(Supplier supplier, Executor executor) {
        return produceInterruptibleCompletableFuture((s) -> CompletableFuture.supplyAsync(s, executor), supplier);
    }
    
    // in case we want to do the same for similar methods later
    private static  CompletableFuture produceInterruptibleCompletableFuture(
            Function,CompletableFuture> completableFutureAsyncSupplier, Supplier action) {
        FutureTask task = new FutureTask<>(action::get);
        return addCancellationAction(completableFutureAsyncSupplier.apply(asSupplier(task)), () ->
                task.cancel(true));
    }
    
    /** Ensures the specified action is executed if the given {@link CompletableFuture} is cancelled.
     */
    public static  CompletableFuture addCancellationAction(CompletableFuture completableFuture,
                                                                 @NonNull Runnable onCancellationAction) {
        completableFuture.whenComplete((result, throwable) -> {
            if (completableFuture.isCancelled()) {
                onCancellationAction.run();
            }
        });
        return completableFuture;  // return original CompletableFuture
    }
    
    /** @return {@link Supplier} wrapper for the given {@link RunnableFuture} which calls {@link RunnableFuture#run()}
     *          followed by {@link RunnableFuture#get()}.
     */
    public static  Supplier asSupplier(RunnableFuture futureTask) throws CompletionException {
        return () -> {
            try {
                futureTask.run();
                try {
                    return futureTask.get();
                } catch (ExecutionException e) {  // unwrap ExecutionExceptions
                    final Throwable cause = e.getCause();
                    throw (cause != null) ? cause : e;
                }
            } catch (CompletionException e) {
                throw e;
            } catch (Throwable t) {
                throw new CompletionException(t);
            }
        };
    }
    

提交回复
热议问题