问题描述
我知道 CompletableFuture
设计不会通过中断来控制其执行,但我想你们中的一些人可能会遇到这个问题.CompletableFuture
是组合异步执行的非常好的方法,但是如果您希望在取消 Future 时中断或停止底层执行,我们该怎么做?或者我们必须接受任何取消或手动完成的 CompletableFuture
不会影响在那里工作以完成它的线程?
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?
在我看来,这显然是一项耗费 executor worker 时间的无用工作.我想知道在这种情况下什么方法或设计可能会有所帮助?
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?
更新
这是一个简单的测试
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!!!");
}
}
}
推荐答案
A CompletableFuture
与可能最终完成它的异步操作无关.
A CompletableFuture
is not related to the asynchronous action that may eventually complete it.
由于(与 FutureTask
不同)这个类不能直接控制导致它完成的计算,取消被视为只是另一种形式的特殊完成.方法 cancel
具有与 completeExceptionally(new CancellationException())
效果相同.
甚至可能没有一个单独的线程来完成它(甚至可能有许多个线程在处理它).即使有,也没有从 CompletableFuture
到任何引用它的线程的链接.
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.
因此,您无法通过 CompletableFuture
来中断任何可能正在运行将完成它的任务的线程.您必须编写自己的逻辑来跟踪任何获取对 CompletableFuture
的引用以完成它的 Thread
实例.
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.
这篇关于如何中断 CompletableFuture 的底层执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!