如何中断CompletableFuture的底层执行

vac*_*ach 23 java concurrency completable-future

我知道CompletableFuture设计不能通过中断来控制它的执行,但我想你们中的一些人可能会遇到这个问题.CompletableFutures是组合异步执行的非常好的方法,但考虑到你希望在取消未来时中断或停止底层执行的情况,我们该怎么做?或者我们必须接受任何取消或手动完成CompletableFuture不会影响在那里完成它的线程?

也就是说,在我看来,显然是一项无用的工作需要时间来执行工人.我想知道在这种情况下哪种方法或设计可能有用?

UPDATE

这是一个简单的测试

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!!!");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 14

A CompletableFuture与最终可能完成它的异步操作无关.

由于(不像FutureTask)这个类没有直接控制导致它完成的计算,因此取消被视为异常完成的另一种形式.方法cancel具有相同的效果completeExceptionally(new CancellationException()).

有可能甚至是一个单独的线程上完成它的工作(甚至有可能是许多线程在它的工作).即使有,也没有从CompletableFuture任何具有引用它的线程的链接.

因此,没有什么可以通过CompletableFuture中断任何可能正在运行某个任务的线程来完成它.你必须编写自己的逻辑来跟踪任何Thread获取CompletableFuture对它的引用的实例,并打算完成它.


这是我认为你可以逃避的执行类型的一个例子.

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();
}
Run Code Online (Sandbox Code Playgroud)

这假定正在执行的任务被设置为正确处理中断.

  • @Vach所以你的确切目标是无法实现的,因为"CompletableFuture"没有潜在的线索.您在线程和"CompletableFuture"之间建立的关联仅由您自己完成.`CompletableFuture`并非如此.使用"Future"和"CompletableFuture"获得的最接近的就是我上面提到的.取消`未来'.如果成功,则取消关联的"CompletableFuture".显然,您可以通过编写自己的`CompletableFuture`来获得所需的行为,但这不是一件容易的事. (2认同)