众所周知,如果我们要使用传统的IO来构建服务器,它必须在某个地方阻塞,所以我们必须使用循环或一线程一套接字模式,所以nio似乎是更好的选择。所以我想知道nio是否永远是更好的选择?
7 回答
恕我直言,阻塞 IO 通常是最简单的使用,除非您有特定要求对系统提出更多要求,否则您应该坚持使用最简单的选项。
下一个最简单的选项是阻塞 NIO,如果我想要比 IO 更高效或控制的东西,我通常更喜欢它。它仍然相对简单,但允许您使用 ByteBuffers。例如ByteBuffers 支持little endian。
一个常见的选项是使用带有选择器的非阻塞 NIO。这引入的大部分复杂性可以由 Netty 或 Mina 等框架处理。如果您需要非阻塞 IO,我建议您使用这样的库,例如因为每台服务器有数千个并发连接。恕我直言,您有数千个连接,您应该考虑拥有更多服务器,除非每个连接的作用非常微不足道。AFAIK google 寻求更多的服务器,而不是每台服务器数千个用户。
更极端的选择是使用 NIO2。这比非阻塞 NIO 更复杂、更冗长。我不知道有什么框架可以很好地支持这一点。即当你这样做时它实际上更快。AFAIK 如果您有 Infiniband(这是它旨在支持的),这似乎值得使用,但如果您有以太网,则可能不值得使用。
如果你想要非阻塞 IO,NIO 不是更好的选择——它是 Java 中的唯一选择。请记住,人们仍然经常使用旧的 IO,因为它更容易编写代码。NIO API 非常原始,它更像是一种低级技术,而不是客户端 API。我建议通过 API 使用 NIO,该 API 为您想要使用非阻塞 IO 解决的问题提供更简单的接口。
有点晚了,但就我个人而言,即使是常规的“日常”文件处理,我也使用 NIO。所以,我使用类似的东西:
1. if(Files.notExists(path)) { }
2. Files.createDirectory(path);
3. Files.newInputStream(path) targetPath.resolve("somefile.txt");
4. Files.newBufferedWriter(path, charset);
5. DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
它对我来说很好。由于 relativize 或 resolveSibling 等方法,我更喜欢 Path 而不是旧的 File。
没有让我觉得比 IO 更复杂。
如果你能证明它引入的不可避免的复杂性是合理的,你只会使用 NIO。如果您在预期负载方面没有任何指导,并且在您的产品/项目是否有资源来维护相关代码方面,那么您应该谨慎行事并使用 IO。
为了让我的回答更有分量,我刚刚花了三个月的时间来维护和修复使用原始 Java NIO(即没有使用总体框架)的集成层。该设计本质上是基于客户端线程将消息添加到队列和少数工作线程执行其 NIO 魔术,然后以基于事件的方式将回复传递回客户端线程。回想起来,我无法证明最初使用 NIO 的决定是合理的,因为它会分散注意力,占用了大量本应花在更高级别业务逻辑上的时间。
您可以使用其中的任何一个,除非您要创建“超快”服务器。
当然,这里的一个好方法是使用 nio,因为它是为高吞吐量任务编写多客户端服务器的新的和现代的方法。
传统 IO 是简单且简化的代码,NIO 更复杂但更灵活。就我而言,我更喜欢将 IO 用于小型流媒体,将 NIO 用于大型流媒体,但 nio 确实更复杂
使用 NIO,我必须创建一个完整的包来管理它,而不是我直接使用片段的 io 包