How to interrupt underlying execution of CompletableFuture

前端 未结 4 1625
自闭症患者
自闭症患者 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:26

    A CompletableFuture is not related to the asynchronous action that may eventually complete it.

    Since (unlike FutureTask) this class has no direct control over the computation that causes it to be completed, cancellation is treated as just another form of exceptional completion. Method cancel has the same effect as completeExceptionally(new CancellationException()).

    There may not even be a separate thread working on completing it (there may even be many threads working on it). Even if there is, there's no link from a CompletableFuture to any thread that has a reference to it.

    As such, there's nothing you can do through CompletableFuture to interrupt any thread that may be running some task that will complete it. You'll have to write your own logic which tracks any Thread instances which acquire a reference to the CompletableFuture with the intention to complete it.


    Here's an example of the type of execution I think you could get away with.

    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(1);
        CompletableFuture completable = new CompletableFuture<>();
        Future future = service.submit(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    if (Thread.interrupted()) {
                        return; // remains uncompleted
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        return; // remains uncompleted
                    }
                }
                completable.complete("done");
            }
        });
    
        Thread.sleep(2000);
    
        // not atomic across the two
        boolean cancelled = future.cancel(true);
        if (cancelled)
            completable.cancel(true); // may not have been cancelled if execution has already completed
        if (completable.isCancelled()) {
            System.out.println("cancelled");
        } else if (completable.isCompletedExceptionally()) {
            System.out.println("exception");
        } else {
            System.out.println("success");
        }
        service.shutdown();
    }
    

    This assumes that the task being executed is setup to handle interruptions correctly.

提交回复
热议问题