在阻塞模式下,Java NIO 相对于传统 I/O 有什么优势?

24

我已经决定不使用异步非阻塞Java NIO。总的来说,它的复杂性与好处相比存在很大的疑问,并且我认为在这个项目中并不值得。

但是,我读到的大部分关于NIO的内容及其与早期java.io.*的比较都集中在非阻塞异步NIO与使用java.io.* 的每个连接一个线程的同步I/O之间的对比上。然而,NIO也可以在同步、阻塞和每个连接一个线程的模式下使用,这似乎很少被讨论。

问题在于:同步、阻塞的NIO与传统的同步、阻塞I/O(java.io.*)是否有性能优势?两者都会采用每个连接一个线程的方式。它们的复杂性如何相比?

请注意,这是一个一般性的问题,但目前我主要关心TCP套接字通信。


3
谨慎需要加分,复杂应该让人望而生畏。 - Bob Cross
你不能在阻塞操作中使用每个线程连接,你需要每个连接两个线程。 - bestsss
除非你只是在处理请求/响应的内容,否则不要使用socket.getInputStream.read()。如果你使用它,你将失去直接缓冲区的所有好处,但实现仍然使用选择器来阻塞读取。我想不出为什么(以及在哪个操作系统上)它应该有好处。 - bestsss
https://dev59.com/pW445IYBdhLWcg3wq8BY#4752404提到在阻塞模式下使用NIO可以更快... - rogerdpack
3个回答

23
NIO相对于“传统”IO的优势在于,NIO可以使用直接缓冲区,允许操作系统对某些操作(例如从网络连接中直接读取到内存映射文件)使用DMA,从而避免将数据复制到中间缓冲区。
如果您正在移动大量数据,并且采用此技术避免了否则将执行的复制操作,则这可能会对性能产生重大影响。

1
NIO包使用一种名为“Buffer”的系统,而不是像java.io.*那样使用“InputStream”和“OutputStream”。+1 - user238033

11

这主要取决于并发连接的数量以及这些连接的繁忙程度。阻塞(每个连接一个标准线程)速度更快,无论是在延迟还是吞吐量方面都是如此(对于简单回显服务器大约快两倍)。因此,如果您的系统可以维护每个连接的线程(规则是少于1000个连接),则选择阻塞方法。如果您有许多大多数处于闲置状态的连接(例如Comet长轮询请求或IMAP空闲连接),则切换到非阻塞架构可能有助于扩展您的系统。


我同意它取决于您想要处理多少并发连接。 我的阈值将是100而不是1000。 1000个线程对于应用程序来说是很多的线程。 (+1) - Romain Hippeau
@Michael Barker 为什么按连接阻塞线程在延迟和吞吐量方面更快? - dublintech
不确定,可能是一个更短/简单的内核转换。 - Michael Barker

0

我可能无法针对具体的技术进行讲解,但异步库提供同步操作以便于调试并不罕见。

例如,如果您遇到问题,可以在不重写整个过程的情况下消除逻辑中的异步部分。这尤其有助于工作,因为同步进程通常更易于处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接