Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interrupt underlying execution of CompletableFuture

I know that CompletableFuture design does not control its execution with interruptions, but I suppose some of you might have this problem. CompletableFutures are very good way to compose async execution, but given the case when you want the underlying execution to be interrupted or stopped when future is canceled, how do we do that? Or we must just accept that any canceled or manually completed CompletableFuture will not impact the thread working out there to complete it?

That is, in my opinion, obviously a useless work that takes time of executor worker. I wonder what approach or design might help in this case?

UPDATE

Here is a simple test for this

public class SimpleTest {    @Test   public void testCompletableFuture() throws Exception {     CompletableFuture<Void> cf = CompletableFuture.runAsync(()->longOperation());      bearSleep(1);      //cf.cancel(true);     cf.complete(null);      System.out.println("it should die now already");     bearSleep(7);   }    public static void longOperation(){     System.out.println("started");     bearSleep(5);     System.out.println("completed");   }    private static void bearSleep(long seconds){     try {       TimeUnit.SECONDS.sleep(seconds);     } catch (InterruptedException e) {       System.out.println("OMG!!! Interrupt!!!");     }   } } 
like image 380
vach Avatar asked Mar 12 '15 15:03

vach


People also ask

How do you cancel Completable futures?

Overview. In Java, we use an instance method of the CompletableFuture class, cancel() , that attempts to cancel the execution of a task.

Does CompletableFuture get block?

The CompletableFuture. get() method is blocking. It waits until the Future is completed and returns the result after its completion.

What is completedStage () method in CompletableFuture interface?

completedFuture​(U value) Returns a new CompletableFuture that is already completed with the given value. static <U> CompletionStage<U> completedStage​(U value) Returns a new CompletionStage that is already completed with the given value and supports only those methods in interface CompletionStage .

What is CompletableFuture void?

CompletableFuture<Void> : The Void tells the user there is no result to be expected.


1 Answers

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<String> 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.

like image 113
Sotirios Delimanolis Avatar answered Oct 06 '22 05:10

Sotirios Delimanolis