Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以在不使用ProjectReactor阻塞线程的情况下等待事件?_Java_Multithreading_Project Reactor - Fatal编程技术网

Java 是否可以在不使用ProjectReactor阻塞线程的情况下等待事件?

Java 是否可以在不使用ProjectReactor阻塞线程的情况下等待事件?,java,multithreading,project-reactor,Java,Multithreading,Project Reactor,Project Reactor是否可以在mono中等待事件/条件,而无需为每个mono使用阻塞线程?有了CompletableFuture我可以完成这样的事情,但我不知道如何使用projectreactor来完成 我的问题是,我需要将请求与响应关联起来。响应时间变化很大,有些甚至永远不会得到回复和超时。在客户端,每个请求阻塞一个线程不是问题,但由于这是一个服务器应用程序,我不希望每个请求生成一个线程来阻塞等待响应 API的外观如下所示: Mono-doRequest(Mono请求); 由于我不

Project Reactor是否可以在mono中等待事件/条件,而无需为每个mono使用阻塞线程?有了
CompletableFuture
我可以完成这样的事情,但我不知道如何使用projectreactor来完成

我的问题是,我需要将请求与响应关联起来。响应时间变化很大,有些甚至永远不会得到回复和超时。在客户端,每个请求阻塞一个线程不是问题,但由于这是一个服务器应用程序,我不希望每个请求生成一个线程来阻塞等待响应

API的外观如下所示:

Mono-doRequest(Mono请求);
由于我不知道如何使用反应堆,我将解释如何使用
CompletableFuture
来澄清我在寻找什么。API如下所示:

CompletableFuture-doRequest(请求);
调用方调用时,会向服务器发出请求,其中包含由该方法生成的相关ID。调用方将返回一个
CompletableFuture
,该方法将对该
CompletableFuture
的引用存储在map中,相关ID作为键

还有一个线程(池),用于接收服务器的所有响应。当它收到响应时,它从响应中获取相关ID,并使用它在映射中查找原始请求(即
CompletableFuture
),并调用
complete(响应)在上面

在这个实现中,每个请求不需要阻塞线程。这基本上更像是一种Vert.X/Netty的思维方式?我想知道如何用ProjectReactor实现这样的事情(如果可能的话)

编辑日期:2019年7月25日:

根据评论中的要求,下面是我将如何使用
completablefuture
实现这一点的示例,以澄清我的想法

我还注意到我犯了一个可能会让人困惑的错误:在
CompletableFuture
示例中,我传递了一个
Mono
作为参数。这应该只是一个“正常”的论点。我很抱歉,我希望我没有让人们太困惑

import java.util.concurrent.CompletableFuture;
导入java.util.concurrent.ConcurrentHashMap;
类NonBlockingCorrelationExample{
/**
*此示例演示如何在不需要(睡眠)的情况下实现请求与响应的关联
*使用{@link CompletableFuture}对每个请求执行线程以等待响应。
*
*因此,本例的主要特点是,始终使用固定(少量)的线程,即使只有一个线程
*会发出数千个请求。
*/
公共静态void main(字符串[]args)引发异常{
RequestResponseService RequestResponseService=新的RequestResponseService();
请求=新请求();
request.correlationId=1;
request.question=“你会说西班牙语吗?”;
CompletableFuture-responseFuture=requestResponseService.doRequest(请求);
responseFuture.whenComplete((response,throwable)->System.out.println(response.answer));
//这里的阻塞调用只是为了在演示完成之前应用程序不会退出。
responseFuture.get();
}
静态类RequestResponseService{
/**此映射中的键是相关ID*/
私有最终ConcurrentHashMap响应=新ConcurrentHashMap();
CompletableFuture-doRequest(请求){
响应=新响应();
response.correlationId=request.correlationId;
CompletableFuture-ResponseFuture=新的CompletableFuture();
responses.put(response.correlationId,reponseFuture);
doNonBlockingFireAndForgetRequest(请求);
回报未来;
}
私有void doNonBlockingFireAndForgetRequest(请求){
//在我的例子中,请求将在请求主题中的MQTT代理(消息总线)上发布。
//现在我们只需要打一个电话,模拟一段时间后收到的响应消息。
模拟器响应();
}
私有void processResponse(响应){
//通常会有一个(小)线程池,它订阅了接收消息的消息总线
//并调用此方法来处理这些消息。
CompletableFuture-responseFuture=responses.get(response.correlationId);
响应未来。完成(响应);
}
void模拟器响应(){
//这只是为了让示例发挥作用,而不是示例的一部分。
新线程(()->{
试一试{
//模拟延迟。
睡眠(10_000);
响应=新响应();
response.correlationId=1;
response.answer=“Si!”;
过程响应(response);
}捕捉(中断异常e){
e、 printStackTrace();
}
}).start();
}
}
静态类请求{
长相关ID;
字符串问题;
}
静态类响应{
长相关ID;
字符串回答;
}
}

是的,这是可能的。您可以使用
reactor.core.publisher.Mono#create
方法来实现它

例如:

public static void main(String[] args) throws Exception {
    RequestResponseService requestResponseService = new RequestResponseService();

    Request request = new Request();
    request.correlationId = 1;
    request.question = "Do you speak Spanish?";


    Mono<Request> requestMono = Mono.just(request)
            .doOnNext(rq -> System.out.println(rq.question));
    requestResponseService.doRequest(requestMono)
            .doOnNext(response -> System.out.println(response.answer))
            // The blocking call here is just so the application doesn't exit until the demo is completed.
            .block();
}

static class RequestResponseService {
    private final ConcurrentHashMap<Long, Consumer<Response>> responses =
            new ConcurrentHashMap<>();

    Mono<Response> doRequest(Mono<Request> request) {
        return request.flatMap(rq -> doNonBlockingFireAndForgetRequest(rq)
                .then(Mono.create(sink -> responses.put(rq.correlationId, sink::success))));
    }

    private Mono<Void> doNonBlockingFireAndForgetRequest(Request request) {
        return Mono.fromRunnable(this::simulateResponses);
    }

    private void processResponse(Response response) {
        responses.get(response.correlationId).accept(response);
    }

    void simulateResponses() {
        // This is just to make the example work. Not part of the example.
        new Thread(() -> {
            try {
                // Simulate a delay.
                Thread.sleep(10_000);

                Response response = new Response();
                response.correlationId = 1;
                response.answer = "Si!";

                processResponse(response);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
publicstaticvoidmain(字符串[]args)引发异常{
RequestResponseService RequestResponseService=新的RequestResponseService();
请求=新请求();
request.correlationId=1;
request.question=“你会说西班牙语吗?”;
Mono requestMono=Mono.just(请求)