17.13 非阻塞 I/O

栏目: Java · 发布时间: 5年前

内容简介:应用程序的web容器通常为每一个客户端请求分配一个服务端线程。开发可扩展的web应用,你必须确保关联请求的线程是没有空闲的,不需要等待一个阻塞操作完成。异步处理提供了在一个新线程处理阻塞操作的机制,把关联请求的线程返回给容器。即使你所有的阻塞操作都在service方法中异步执行,关联客户端请求的线程基于input/output也可能出于暂时空闲状态。例如,如果一个客户端在一个很慢的网络连接上提交一个大的HTTP POST请求,server读取请求的速度比客户端上传的速度快很多。使用TIO,容器关联请求的线程

应用程序的web容器通常为每一个客户端请求分配一个服务端线程。开发可扩展的web应用,你必须确保关联请求的线程是没有空闲的,不需要等待一个阻塞操作完成。异步处理提供了在一个新线程处理阻塞操作的机制,把关联请求的线程返回给容器。即使你所有的阻塞操作都在service方法中异步执行,关联客户端请求的线程基于input/output也可能出于暂时空闲状态。

例如,如果一个客户端在一个很慢的网络连接上提交一个大的HTTP POST请求,server读取请求的速度比客户端上传的速度快很多。使用TIO,容器关联请求的线程有时会出于空闲状态,因为要等待客户端的请求的其余部分。

JAVA EE异步模式处理请求时,提供支持servlet和filter的NIO。下面的步骤总结了在service方法中如何使用NIO处理请求和写出响应:

1. 如 Asynchronous Processing章节描述,把请求设置为异步模式  
2. 在service方法中从请求和响应对象中获得一个请求流或一个响应流
3. 分配给请求流一个监听器或者分配给响应流一个监听器 
4. 在监听器的回调方法中处理请求和响应

NIO 支持类 javax.servlet.ServletInputStream

方法签名:void setReadListener(ReadListener rl)

描述:将输入流与包含回调方法的监听器对象关联,以异步读取数据。提供的监听器对象可以是一个匿名类或者使用其他的机制给监听器对象传入输入流。

方法签名:boolean isReady()

方法描述:如果数据可以无阻塞读取,返回true

方法签名:boolean isFinished()

方法描述:当所有数据读取完毕后,返回true

NIO 支持类 javax.servlet.ServletOutputStream

方法签名:void setWriteListener(WriteListener wl)

方法描述:将此输出流与包含回调方法的侦听器对象关联,以异步写入数据。

您将写入侦听器对象提供为匿名类,或使用其他机制将输出流传递给写入侦听器对象。

方法签名:boolean isReady()

方法描述:如果数据可以无阻塞写入,返回true

NIO监听器支持接口

接口名称:ReadListener

接口方法:void onDataAvailable()、void onAllDataRead()、void onError(Throwable t)

描述:ServletInputStream当数据可以有效读取、当数据读取完毕、当发生一个错误时调用监听器的这些方法。

接口名称:WriteListener

接口方法:void onWritePossible()、void onError(Throwable t)

描述:ServletOutputStream当数据可以无阻塞读取、当发生一个错误时调用监听器的这些方法。

使用NIO读取大的HTTP POST请求

本节代码展示了在servlet对象中怎么读取一个大的HTTP POST数据,通过把请求放入异步模式中并使用NIO功能。

@WebServlet(urlPatterns={"/asyncioservlet"}, asyncSupported=true)
public class AsyncIOServlet extends HttpServlet {
   @Override
   public void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
                      throws IOException {
      final AsyncContext acontext = request.startAsync();
      final ServletInputStream input = request.getInputStream();
      
      input.setReadListener(new ReadListener() {
         byte buffer[] = new byte[4*1024];
         StringBuilder sbuilder = new StringBuilder();
         @Override
         public void onDataAvailable() {
            try {
               do {
                  int length = input.read(buffer);
                  sbuilder.append(new String(buffer, 0, length));
               } while(input.isReady());
            } catch (IOException ex) { ... }
         }
         @Override
         public void onAllDataRead() {
            try {
               acontext.getResponse().getWriter()
                                     .write("...the response...");
            } catch (IOException ex) { ... }
            acontext.complete();
         }
         @Override
         public void onError(Throwable t) { ... }
      });
   }
}

此示例使用@WebServlet批注参数asyncSupported = true声明具有异步支持的Web Servlet。服务方法首先通过调用请求对象的startAsync()方法将请求置于异步模式,这是使用非阻塞I / O所必需的。然后,服务方法获得与请求相关联的输入流,并分配定义为内部类的读取侦听器。侦听器在可用时读取部分请求,然后在完成读取请求时将一些响应写入客户端。


以上所述就是小编给大家介绍的《17.13 非阻塞 I/O》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Weaving the Web

Weaving the Web

Tim Berners-Lee / Harper Paperbacks / 2000-11-01 / USD 15.00

Named one of the greatest minds of the 20th century by Time , Tim Berners-Lee is responsible for one of that century's most important advancements: the world wide web. Now, this low-profile genius-wh......一起来看看 《Weaving the Web》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试