我们知道,如果我们想使用传统的IO来构建服务器,它必须在某个地方阻塞,所以我们必须使用循环或一线程一套接字模式,所以nio似乎是更好的选择。所以我想知道 nio 是否永远是更好的选择?
恕我直言,阻塞 IO 通常是最简单的使用方式,除非您有对系统有更多要求的特定要求,否则您应该坚持使用最简单的选项。
下一个最简单的选择是阻塞 NIO,如果我想要比 IO 更高的效率或控制力,我通常更喜欢它。它仍然相对简单,但允许您使用 ByteBuffers。例如ByteBuffers 支持小端。
一个常见的选择是将非阻塞 NIO 与选择器结合使用。这带来的大部分复杂性可以通过 Netty 或 Mina 等框架来处理。如果你需要非阻塞IO,我建议你使用这样的库。因为每台服务器有数千个并发连接。恕我直言,您有数千个连接,您应该考虑拥有更多服务器,除非每个连接的作用非常微不足道。据我所知,谷歌寻求更多的服务器,而不是每台服务器数千个用户。
更极端的选择是使用NIO2。这比非阻塞 NIO 写起来更加复杂和冗长。我不知道有什么框架可以很好地支持这一点。也就是说,当你这样做时,它实际上会更快。 AFAIK 如果您有 Infiniband(这是它设计支持的),那么这似乎值得使用,但如果您有以太网,则可能不值得使用。
如果你想要非阻塞 IO,NIO 并不是更好的选择——它是 Java 中“唯一”的选择。请记住,人们仍然经常使用旧的 IO,因为它的编码要简单得多。 NIO API 非常原始,与其说是客户端 API,不如说是一种底层技术。我建议通过 API 使用 NIO,该 API 为您想要使用非阻塞 IO 解决的问题提供更简单的接口。
为了给我的答案一些分量,我刚刚花了三个月的时间维护和修复使用原始 Java NIO(即没有使用总体框架)的集成层。该设计本质上是基于客户端线程将消息添加到队列和少量工作线程执行其 NIO 魔法,然后以基于事件的方式将回复传递回客户端线程。回想起来,我无法证明最初使用 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);
对我来说效果很好。我更喜欢 Path 而不是旧的 File,因为有 relativize 或resolveSibling 等方法。
我觉得并不比 IO 更复杂。
当然,这里的一个好方法是使用 nio,因为它是为高吞吐量任务编写多客户端服务器的新且现代的方法。
流式传输,使用 NIO 进行大流式传输,但 nio 确实更复杂 使用 NIO,我必须创建一个完整的包来管理它,而不是我直接使用的 io 包
snippet