为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕侠2389804 2023-03-09 15:27:10
正如在一个单独的问题中所描述的,当使用 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 对象来存储流。当交换器处于阻塞模式时,输入流方法变得可用,除此之外,阻塞模式和非阻塞模式之间目前没有主要区别如何将这个阻塞调用变成非阻塞调用?
查看完整描述

1 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

正确的方法是在 IO 线程中实际执行逻辑,如果它是非阻塞的。否则,将请求委托给专用线程,如下所示:


public class Example {


  public static void main(String[] args) {

    Undertow server = Undertow.builder()

        .addListener(8080, "localhost")

        .setHandler(new HttpHandler() {

          public void handleRequest(HttpServerExchange exchange)

              throws Exception {


            if (valueIsPresentInCache(exchange)) {

              getValueFromCache();  // non-blocking, can be done from IO thread           

            } else {


              if (exchange.isInIoThread()) {

                exchange.dispatch(this);

                // we return immediately, otherwise this request will be

                // handled both in IO thread and a Worker thread, throwing

                // an exception

                return;

              }


              fetchValueFromDatabase(); // blocking!!!


            }

          }

        })

        .build();

    server.start();

  }

}


查看完整回答
反对 回复 2023-03-09
  • 1 回答
  • 0 关注
  • 114 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信