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

问题描述

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





更新



这是一个简单的测试

 公共类SimpleTest {

@Test
public void testCompletableFuture()抛出异常{
CompletableFuture< Void> cf = CompletableFuture.runAsync(() - > longOperation());

bearSleep(1);

//cf.cancel(true);
cf.complete(null);

System.out.println(它现在应该已经死了);
bearSleep(7);
}

public static void longOperation(){
System.out.println(started);
bearSleep(5);
System.out.println(已完成);
}

private static void bearSleep(long seconds){
try {
TimeUnit.SECONDS.sleep(seconds);
} catch(InterruptedException e){
System.out.println(OMG !!! Interrupt !!!);
}
}
}


解决方案

与最终可能完成它的异步操作无关。

甚至可能 一个单独的线程正在努力完成它(甚至可能很多工作的线程)。即使有,也没有从 CompletableFuture 链接到任何引用它的线程。



As这样,你无法通过 CompletableFuture 来中断任何可能正在运行某个任务的线程来完成它。您必须编写自己的逻辑来跟踪任何 Thread 实例,这些实例获取对 CompletableFuture 的引用完成它。






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

  public static void main(String [] args)throws Exception {
ExecutorService service = Executors.newFixedThreadPool(1);
CompletableFuture< String> completable = new CompletableFuture<>();
未来<?> future = service.submit(new Runnable(){
@Override
public void run(){
for(int i = 0; i< 10; i ++){
if(Thread.interrupted()){
return; //保持未完成
}
尝试{
Thread.sleep(1000);
} catch(InterruptedException e ){
return; //仍然未完成
}
}
completable.complete(done);
}
});

Thread.sleep(2000);

//在两个
boolean cancel = future.cancel(true)中不是原子的;
if(cancelled)
completable.cancel(true); //如果执行已经完成,则可能没有被取消
if(completable.isCancelled()){
System.out.println(cancelled);
} else if(completable.isCompletedExceptionally()){
System.out.println(exception);
} else {
System.out.println(成功);
}
service.shutdown();
}

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


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?

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!!!");
    }
  }
}
解决方案

A CompletableFuture is not related to the asynchronous action that may eventually complete it.

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.

这篇关于如何中断CompletableFuture的底层执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 21:54