Java NIO 学习笔记(七)----NIO/IO 的对比和总结 (2)

想象一下,在第一次读取(缓冲)调用之后,是否所有读入缓冲区的内容都是半行。 例如,“Name:cz”。 你能处理这些数据吗? 显然不能。 在处理任何数据之前,我们需要等待至少一整行数据进入缓冲区。

那么怎么知道缓冲区是否包含足够的数据来处理它?唯一方法是查看缓冲区中的数据。 这样将导致:在知道所有数据是否存在之前,可能需要多次检查缓冲区中的数据(轮询)。 这既低效又可能在程序设计方面变得混乱。 例如:

ByteBuffer buffer = ByteBuffer.allocate(64); int bytesRead = inChannel.read(buffer); while(! bufferFull(bytesRead) ) { bytesRead = inChannel.read(buffer); }

bufferFull() 方法必须跟踪读入缓冲区的数据量,并返回 true 或 false ,具体取决于缓冲区是否已满。 换句话说,如果缓冲区已准备好进行处理,则认为它已满。

bufferFull() 方法扫描缓冲区,并且必须使缓冲区保持与调用 bufferFull() 方法之前相同的状态。 如果不这样,则可能无法在正确的位置继续读入下一个数据到缓冲区中。 这不是不可能的,但这是另一个需要注意的问题。

如果缓冲区已满,则可以对其进行处理。 如果缓冲区还没满,有可能让程序先部分处理已到达的数据,这在的特定情况下是有意义的。 但在许多情况下,不完整的数据没有处理的意义。

这个图中说明了 is-data-in-buffer-ready 循环:

image

总结

NIO 允许仅使用一个(或几个)线程来管理多个通道(网络连接或文件),但成本是解析数据可能比从阻塞流中读取数据时更复杂一些。

如果需要同时管理数千个打开的连接,每个只发送一些数据,例如聊天服务器,这在 NIO 中实现服务器可能是一个优势。 同样,如果需要与其他计算机保持大量开放连接,例如,在 P2P 网络中,使用单个线程来管理所有出站连接可能是一个优势。 下图中说明了这种一个线程,多个连接的设计:

image

但如果拥有较少带宽的连接,一次连接的数据量较大,那么经典的 IO 服务器实现可能更合适的。 下图说明了这种典型的 IO 服务器设计:

image

所以,应该根据具体的情况分析,选择更适合的,而不是更新的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdxwx.html