猿问

如何在 Undertow 的非阻塞处理程序中执行阻塞代码?

正如在一个单独的问题中所描述的,当使用 Undertow 时,所有的处理都应该在一个专用的 Worker 线程池中完成,它看起来像这样:


public class Start {


  public static void main(String[] args) {

    Undertow server = Undertow.builder()

        .addListener(8080, "localhost")

        .setHandler(new HttpHandler() {

          public void handleRequest(HttpServerExchange exchange)

              throws Exception {

            if (exchange.isInIoThread()) {

              exchange.dispatch(this);

              return;

            }

            exchange.getResponseHeaders()

                    .put(Headers.CONTENT_TYPE, "text/plain");

            exchange.getResponseSender()

                    .send("Hello World");

          }

        })

        .build();

    server.start();

  }

}

我知道这BlockingHandler可以用于明确告诉 Undertow 将请求安排在专用线程池上以阻止请求。HttpHandler我们可以通过将 包装在 的实例中来调整上面的示例BlockingHandler,如下所示:


        .setHandler(new BlockingHandler(new HttpHandler() {

这适用于我们知道总是阻塞的呼叫。


但是,如果某些代码大部分时间是非阻塞的,但有时需要阻塞调用,如何将阻塞调用变成非阻塞调用?例如,如果请求的值存在于缓存中,则以下代码不会阻塞(它只是从 some 中获取Map<>),但如果不存在,则必须从数据库中获取。


public class Start {


  public static void main(String[] args) {

    Undertow server = Undertow.builder()

        .addListener(8080, "localhost")

        .setHandler(new HttpHandler() {

          public void handleRequest(HttpServerExchange exchange)

              throws Exception {

            if (exchange.isInIoThread()) {

              exchange.dispatch(this);

              return;

            }

            if (valueIsPresentInCache(exchange)) {

              return valueFromCache;  // non-blocking

            } else {

              return fetchValueFromDatabase(); // blocking!!!

            }

          }

        })

        .build();

    server.start();

  }

}

根据文档,有一个方法HttpServerExchange.startBlocking(),但根据 JavaDoc,除非你真的需要使用输入流,否则这个调用仍然是一个阻塞的。


调用此方法将交换置于阻塞模式,并创建一个 BlockingHttpExchange 对象来存储流。当交换器处于阻塞模式时,输入流方法变得可用,除此之外,阻塞模式和非阻塞模式之间目前没有主要区别


如何将这个阻塞调用变成非阻塞调用?


慕侠2389804
浏览 115回答 1
1回答

开心每一天1111

正确的方法是在 IO 线程中实际执行逻辑,如果它是非阻塞的。否则,将请求委托给专用线程,如下所示:public class Example {&nbsp; public static void main(String[] args) {&nbsp; &nbsp; Undertow server = Undertow.builder()&nbsp; &nbsp; &nbsp; &nbsp; .addListener(8080, "localhost")&nbsp; &nbsp; &nbsp; &nbsp; .setHandler(new HttpHandler() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void handleRequest(HttpServerExchange exchange)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (valueIsPresentInCache(exchange)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getValueFromCache();&nbsp; // non-blocking, can be done from IO thread&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (exchange.isInIoThread()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exchange.dispatch(this);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // we return immediately, otherwise this request will be&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // handled both in IO thread and a Worker thread, throwing&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // an exception&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fetchValueFromDatabase(); // blocking!!!&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; .build();&nbsp; &nbsp; server.start();&nbsp; }}
随时随地看视频慕课网APP

相关分类

Java
我要回答