Java CompletableFuture.complete()块

Java CompletableFuture.complete()块,java,multithreading,future,reactor,completable-future,Java,Multithreading,Future,Reactor,Completable Future,我在java中使用CompletableFuture时遇到了一个问题。 我有两个select请求,它们是在从服务器接收响应时填写的 在连接线程(线程1)(使用reactor)中,我使用: 在其他线程(线程2)中,我使用: 我的情况是,系统打印出“接收所有未来”,但调用future.complete(结果)时线程1被阻塞它无法退出该命令。 如果在线程2中,我使用CompletableFuture.allOf(allOfSelect.get(),线程1将正确运行。但是使用CompletableFut

我在java中使用CompletableFuture时遇到了一个问题。 我有两个select请求,它们是在从服务器接收响应时填写的

在连接线程(线程1)(使用reactor)中,我使用:

在其他线程(线程2)中,我使用:

我的情况是,系统打印出“接收所有未来”,但调用
future.complete(结果)时线程1被阻塞它无法退出该命令。
如果在线程2中,我使用
CompletableFuture.allOf(allOfSelect.get()
,线程1将正确运行。但是使用
CompletableFuture.get()
会降低性能,所以我想使用
CompletableFuture.whenComplete()

有人能帮我解释一下阻塞的原因吗


谢谢

调用
complete
会触发所有相关
CompletionStage
s

因此,如果您以前已在完成时向
注册了
BiConsumer
complete
将在其调用线程中调用它。在您的情况下,当完成时,
BiConsumer
传递给
时,对
complete
的调用将返回。这在中进行了描述

为非异步方法的依赖完成提供的操作可能是 由完成当前任务的线程执行
CompletableFuture
,或由完成方法的任何其他调用方执行

(另一个调用者的情况正好相反,如果目标
CompletableFuture
已经完成,则调用
whenComplete
的线程实际上会应用
BiConsumer
。)

下面是一个小程序来说明这种行为:

public static void main(String[] args) throws Exception {
    CompletableFuture<String> future = new CompletableFuture<String>();
    future.whenComplete((r, t) -> {
        System.out.println("before sleep, executed in thread " + Thread.currentThread());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after sleep, executed in thread " + Thread.currentThread());
    });

    System.out.println(Thread.currentThread());
    future.complete("completed");
    System.out.println("done");
}
显示在主线程中应用了
BiConsumer
,即调用
complete
的线程

您可以使用强制在单独的线程中执行
BiConsumer

[…]使用此阶段的默认值执行给定操作 此阶段完成时的异步执行功能

比如说,

public static void main(String[] args) throws Exception {
    CompletableFuture<String> future = new CompletableFuture<String>();
    CompletableFuture<?> done = future.whenCompleteAsync((r, t) -> {
        System.out.println("before sleep, executed in thread " + Thread.currentThread());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after sleep, executed in thread " + Thread.currentThread());
    });

    System.out.println(Thread.currentThread());
    future.complete("completed");
    System.out.println("done");
    done.get();
}

显示
BiConsumer
已在单独的线程中应用。

非常感谢。你对线程的解释很清楚。在我第一次使用CompletableFuture时,我只使用它来调用从客户端到服务器的单个请求(如SELECT、UPDATE等),因此它完全按照我的预期运行(客户端等待响应并填充未来)。但现在,我在处理事务时遇到了一个问题,因为它有阶段。我想在所有SELECT done之后立即将future作为CompletableFuture返回,但是只有在其他执行(更新、删除)有结果时,future才会被填充。你能给我一个解决方案来处理连锁店的事情吗。非常感谢!我想按顺序做一些事情,比如:1。选择->CompletableFuture 2。PREPARE->CompletableFuture(也执行返回CompletableFutures的其他调用)。3.COMMIT->CompletableFuture,事务必须在注册时立即返回给调用方。非常感谢!
public static void main(String[] args) throws Exception {
    CompletableFuture<String> future = new CompletableFuture<String>();
    future.whenComplete((r, t) -> {
        System.out.println("before sleep, executed in thread " + Thread.currentThread());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after sleep, executed in thread " + Thread.currentThread());
    });

    System.out.println(Thread.currentThread());
    future.complete("completed");
    System.out.println("done");
}
Thread[main,5,main]
before sleep, executed in thread Thread[main,5,main]
after sleep, executed in thread Thread[main,5,main]
done
public static void main(String[] args) throws Exception {
    CompletableFuture<String> future = new CompletableFuture<String>();
    CompletableFuture<?> done = future.whenCompleteAsync((r, t) -> {
        System.out.println("before sleep, executed in thread " + Thread.currentThread());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("after sleep, executed in thread " + Thread.currentThread());
    });

    System.out.println(Thread.currentThread());
    future.complete("completed");
    System.out.println("done");
    done.get();
}
Thread[main,5,main]
done
before sleep, executed in thread Thread[ForkJoinPool.commonPool-worker-1,5,main]
after sleep, executed in thread Thread[ForkJoinPool.commonPool-worker-1,5,main]