Java:在一个链中组合几个可完成的未来

Java:在一个链中组合几个可完成的未来,java,completable-future,Java,Completable Future,我希望有一个方法来发送请求,然后通过UDP接收响应。 以下是我目前的发展: public <T extends ObjectSerializable, U extends ObjectDeserializable> CompletableFuture<Object> execute(T request, U response) { var resultFuture = sender.asyncSend(request); /*CompletableFuture&l

我希望有一个方法来发送请求,然后通过UDP接收响应。 以下是我目前的发展:

public <T extends ObjectSerializable, U extends ObjectDeserializable>
CompletableFuture<Object> execute(T request, U response)
{
    var resultFuture = sender.asyncSend(request); /*CompletableFuture<Void>*/
    resultFuture.thenAccept((nullObj) -> {
        try {
            receiver.asyncReceive(response).get(); /*CompletableFuture<Void>*/
        }catch (Exception e) {
            throw new FutureExecutionException(e.getMessage());
        }
    }).thenRun(()  -> {
        System.out.println("Send->Receive finished");
    });

    return resultFuture;
}
公共
CompletableFuture执行(T请求,U响应)
{
var resultFuture=sender.asyncSend(请求);/*CompletableFuture*/
结果未来。然后接受((nullObj)->{
试一试{
receiver.asyncReceive(response.get();/*CompletableFuture*/
}捕获(例外e){
抛出新的FutureExecutionException(例如getMessage());
}
}).然后运行(()->{
System.out.println(“发送->接收完成”);
});
返回结果未来;
}
问题是:我是否必须在
内等待未来。然后接受
?是否保证在receiver.asyncReceive完成后执行
.thenRun

我这样组合CompletableFutures是否正确?

这是一个看起来不错的解决方案

public <T extends ObjectSerializable, U extends ObjectDeserializable>
CompletableFuture<Void> execute(T request, U response)
{
    return sender.asyncSend(request)
            .thenCompose( result -> receiver.asyncReceive(response))
            .thenRun( () -> System.out.println("Send-Receive finished"));
}
公共
CompletableFuture执行(T请求,U响应)
{
返回发送者。异步发送(请求)
.thenCompose(结果->接收方.asyncReceive(响应))
.then运行(()->System.out.println(“发送-接收完成”);
}

如果您的
execute
作为参数,那么这将容易得多。然后您可以将该类传递给
receiver.asyncReceive
。在内部,您可以(假设这样的类有一个默认构造函数)创建一个实例并用所有字段填充它。这很容易通过以下途径实现:

clazz.getConstructor().newInstance()
然后,您的代码将返回一个
CompletableFuture
,因此您的方法将类似于:

    public <T extends ObjectSerializable, U extends ObjectDeserializable>
              CompletableFuture<U> execute(T request, Class<U> response){
         return sender.asyncSend(request)
                      .thenCompose(nothing -> receiver.asyncReceive(response));
    }
公共
CompletableFuture执行(T请求、类响应){
返回发送者。异步发送(请求)
.thenCompose(nothing->receiver.asyncReceive(response));
}

我也不确定您的
asyncSend
是否应该返回一个
CompletableFuture
,可能这个函数也可以将
作为参数,并返回正确的类型作为
CompletableFuture
,但是您不需要
asyncReceive
,我想…

我希望有一个方法来发送请求,然后通过UDP接收响应,但这里您返回一个
CompletableFuture
,您不知道它是否已完成。这就是你想要的吗?是的,因为稍后我会简单地调用。获取并检索响应对象。如果超时,我会得到ExecutionException。如果您对完整的源代码感兴趣,我可以直接与您共享。什么响应对象?调用阻塞
get
时,您将得到一个空值。另外,方法名没有任何意义,它没有潜在地执行任何东西。它可以执行,但只有当
发送方.asyncSend(请求)
之前准备就绪时,它才能执行。然后将compose(result->receiver.asyncsreceive(response))
附加到以前的将来。get向我保证响应对象已经在接收方内部反序列化,我可以安全地访问它。据我所知,thenCompose只有在前一个未来还可以的情况下才会执行,我错了吗?至少我的测试显示了这种行为你有很多我没有的背景。与返回类型相反,
response
作为
execute
方法的参数是非常奇怪的。。。似乎您的
receiver.asyncReceive(response)
正在某个地方存储响应,因此当您稍后调用
get
并成功时,您将从“某个地方”获得响应。不