Servlet API 和 NIO: 最终组合在一起
2009-11-08 00:00:00 来源:WEB开发网注意,这不一定提高整体的吞吐量,但确实改善了用户体验。即使在超载的情况下,也会给每个线程一个处理时间片。这一原则同样适用于基于标准 Java I/O 的服务器;不过这些服务器是受到限制的,因为会 要求 它们为每个打开的 socket 连接分配一个线程。NIO 服务器完全不用担心这一点,因此它们可以扩展到大量用户。最后的结果是 NIO 服务器仍然需要线程,只是不需要那么多。
请求处理
Client 类有两个用途。首先,通过把传入的非阻塞 I/O 转换成可由 Servlet API 消费的阻塞 InputStream ,它解决了阻塞/非阻塞问题。其次,它管理特定客户机的请求状态。因为当全部读取消息时,非阻塞通道没有给出任何提示,所以强制我们在协议层处理这一情况。 Client 类在任意指定的时刻都指出了它是否正在参与进行中的请求。如果它准备处理新请求, write() 方法就会为请求处理而将该客户机排到队列中。如果它已经参与了请求,它就只是使用 PipedInputStream 和 PipedOutputStream 类把传入的字节转换成一个 InputStream 。
图 1 展示了两个线程围绕管道进行交互。主线程把从通道读取的数据写到管道中。管道把相同的数据作为 InputStream 提供给消费者。管道的另一个重要特性是:它是进行缓冲处理的。如果没有进行缓冲处理,主线程在尝试写到管道时就会阻塞。因为主线程单独负责所有客户机间的多路复用,因此我们不能让它阻塞。
图 1. PipedInput/OutputStream
在 Client 自己排队后,工作线程就可以消费它了。 RequestHandlerThread 类承担了这个角色。至此,我们已经看到主线程是如何连续地循环的,它要么接受新客户机,要么读取新的 I/O。工作线程循环等待新请求。当客户机在请求队列上变为可用时,它就马上被 remove() 方法中阻塞的第一个等待线程所消费。
更多精彩
赞助商链接