26

所以在这里我正在阅读我最喜欢的软件模式书籍之一(面向模式的软件架构 - 并发和网络对象的模式),特别是关于 Proactor/Reactor 异步 IO 模式的部分。我可以看到通过使用可选通道,我可以很容易地实现 Reactor 风格的异步 IO 机制(并且已经这样做了)。但是,我看不到如何使用非阻塞写入实现适当的 Proactor 机制。这是利用操作系统管理的非阻塞写功能。

操作系统特定调用支持的功能,如win32 下的GetQueuedCompletionStatus 。

我确实看到 Java 7 通过异步完成处理程序为 NIO 带来了一些更新(这似乎是正确的方向)。话虽这么说......鉴于缺乏对操作系统管理的异步操作(特别是异步写入)的统一跨平台支持,我假设这是一个不利用本机操作系统支持的准实现。

所以我的问题是,在 Java 中基于前摄器的 IO 处理是否可能以一种有利于特定场景的方式进行处理?并且,如果 Java NIO 确实支持基于前摄器的 IO 处理(在 Java 6 或 Java 7 中),是否正在使用操作系统管理的异步 IO 支持(即来自操作系统的完成回调)?此外,如果实现纯粹是在 VM 中,那么性能优势将非常小,以至于使用主动事件处理仅提供一种不同(可能更简单)的方式来构建并发网络处理软件。

对于任何对主动事件处理感兴趣的人来说,这是一篇很好的文章,它概述了优点/缺点,并与传统的每连接线程和反应式 IO 模型进行了比较。

4

4 回答 4

23

这其中涉及很多因素。我将尝试尽可能地总结我的发现(意识到关于反应器和前摄器 IO 处理实现的有用性存在争议的事实)。

在 Java 中,基于前摄器的 IO 处理是否可能以有利于用于特定场景的方式进行。

Java 1.4 引入了与异步 IO 不同的非阻塞 IO。Java SE 7 引入了带有 JSR203 的异步 IO,使得“真正的”前摄器风格的 IO 处理实现成为可能。

请参阅AsyncrhonousSocketChannelAsynchronousServerSocketChannel

并且,如果 Java NIO 确实支持基于前摄器的 IO 处理(在 Java 6 或 Java 7 中),是否正在使用操作系统管理的异步 IO 支持(即来自操作系统的完成回调)?

通读 JSR 203 规范,肯定支持使用新异步通道的完成处理程序,据报道正在使用本机 OS 功能,但我尚未确定在何种程度上。在分析 Java 7 源代码后,我可能会跟进这个问题(除非有人打败了我)。

此外,如果实现纯粹是在 VM 中,那么性能优势将非常小,以至于使用主动事件处理仅提供一种不同(可能更简单)的方式来构建并发网络处理软件。

我无法找到有关 Java 7 中新的异步 IO 功能的任何性能比较。我相信它们将在不久的将来可用。

与往常一样,当提出不止一种方法来解决问题时,哪种方法更好的问题几乎总是用“取决于”来回答。主动事件处理(使用异步完成处理程序)包含在 Java 7 中,不能没有目的就简单地存在。对于某些应用程序,使用这种 IO 处理是有意义的。从历史上看,proactor 具有良好适用性的一个常见示例是在 HTTP 服务器中频繁发出许多短请求。要获得更深入的解释,请阅读此内容(仅用于突出 proactor 的优点,因此请尝试忽略示例代码是 C++ 的事实)。

IMO 似乎很明显,在许多情况下,反应堆/前摄器使使用更传统方法的非常简单的设计变得复杂,而在其他更复杂的系统中,它们提供了高度的简化和灵活性。

. . .

在旁注中,我强烈建议阅读以下有关 NIO 的演示文稿,其中提供了 NIO 和“传统”方法之间的性能比较。尽管我也建议谨慎对待呈现的结果,因为基准测试中的 NIO 实现基于 Java 1.4 之前的 NBIO NIO 库,而不是 1.4 中的 NIO 实现。

于 2011-04-05T12:33:20.853 回答
9

我会检查您是否真的需要担心阻止写入。

没有数据可读取的读取块。这可能是大部分时间。但是,当缓冲区已满时,写入会阻塞,这种情况很少发生,通常表示连接速度慢或消费者失败。

如果您想要非阻塞 IO,请为读取执行此操作,并为写入执行此操作。

注意:将阻塞 IO 与 NIO 一起使用通常更简单,并且可以执行非阻塞 NIO,除非您有 1000 个连接,否则您可能会发现增加的复杂性不值得。(而且可能不是最好的选择)

于 2011-04-03T15:41:48.230 回答
2

我最喜欢的软件模式书籍之一(面向模式的软件架构 - 并发和网络对象的模式)

就这一点而言,那本书已经过时了,并且在任何时候都具有可疑的相关性。它源于 1990 年代后期的设计模式狂热,当时人们齐心协力地将整个计算机科学简化为设计模式。

我现在的观点是,NIO 已经是一个框架和设计模式。

于 2011-04-05T09:00:11.870 回答
2

NIO 已经提供了反应模式(选择器)的实现,NIO2 增加了主动模式(完成处理程序)的实现。

不要重新发明它,只需使用它,因为你无法超越它的性能——毕竟这是任何试图避免阻塞 i/o 的人——使用纯 Java 解决方案,因为你无法访问非底层操作系统的阻塞/异步特性。但是 NIO 和 NIO2 使用了这些,这使得它们很快。

于 2015-05-27T02:18:44.430 回答