如何中断 CompletableFuture 的底层执行 [英] How to interrupt underlying execution of CompletableFuture

查看:52
本文介绍了如何中断 CompletableFuture 的底层执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 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. 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?

在我看来,这显然是一项耗费 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()) 效果相同.

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()).

甚至可能没有一个单独的线程来完成它(甚至可能有许多个线程在处理它).即使有,也没有从 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 的底层执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆