I know that CompletableFuture
design does not control its execution with interruptions, but I suppose some of you might have this problem. CompletableFuture
s 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!!!"); } } }
Overview. In Java, we use an instance method of the CompletableFuture class, cancel() , that attempts to cancel the execution of a task.
The CompletableFuture. get() method is blocking. It waits until the Future is completed and returns the result after its completion.
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 .
CompletableFuture<Void> : The Void tells the user there is no result to be expected.
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. Methodcancel
has the same effect ascompleteExceptionally(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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With