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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…