Java - 用于非阻塞套接字的多个线程中的多个选择器

mic*_*ett 6 java multithreading nio css-selectors

我正在编写一个Java应用程序,它将实例化一个类的对象,以表示已在我的应用程序的另一端连接并注册到外部系统的客户端.

每个客户端对象都有两个嵌套类,表示前端和后端.前端类将不断从实际客户端接收数据,并将指示和数据发送到后端类,后端类将从前端获取数据并使用适当的格式和协议将其发送到外部系统该系统需要.

在设计中,我们希望将客户端对象的每个实例化都作为一个线程.然后,在每个线程中自然会有两个插槽[编辑],每个插槽都有自己的NIO通道[/ EDIT],一个客户端,一个系统端分别位于前端和后端.但是,这现在引入了对非阻塞套接字的需求.我一直在阅读这里的教程,解释如何在主线程中安全地使用Selector来处理所有带连接的线程.

但是,我需要的是多个选择器 - 每个选择器都在自己的线程中运行.通过阅读上述教程,我了解到Selector中的键集不是线程安全的.这是否意味着在我们自己的repsective线程中实例化的单独选择器可能会创建冲突的密钥,如果我尝试给它们各自的一对套接字和通道?将选择器移动到主线程的可能性很小,但根据我已经给出的软件要求,它远非理想.谢谢您的帮助.

小智 3

只要您不向两个选择器实例注册具有相同兴趣(OP_READ / OP_WRITE 等)的相同通道,使用多个选择器就可以了。向多个选择器实例注册同一通道可能会导致这样的问题:selector1.select() 可能会消耗selector2.select() 可能感兴趣的事件。

大多数平台上的默认选择器都是基于 poll() [或 epoll()] 的。

Selector.select 内部调用int poll( ListPointer, Nfdsmsgs, Timeout) method.

        where the ListPointer structure can then be initialized as follows:

    list.fds[0].fd = file_descriptorA;
    list.fds[0].events = requested_events;
    list.msgs[0].msgid = message_id;
    list.msgs[0].events = requested_events;
Run Code Online (Sandbox Code Playgroud)

也就是说,我建议使用 ROX RPC nio 教程中提到的单个选择线程。NIO 实现依赖于平台,很可能在一个平台上有效的方法可能在另一个平台上无效。我也看到过小版本的问题。例如,AIX JDK 1.6 SR2 使用基于 poll() 的选择器 - PollSelectorImpl 和相应的选择器提供程序作为 PollSelectorProvider,我们的服务器运行良好。当我迁移到 AIX JDK 1.6 SR5(它使用基于轮询集接口的优化选择器 (PollSetSelectorImpl))时,我们在服务器中的 select() 和 socketchannel.close() 中遇到了频繁的挂起。我看到的原因之一是我们在应用程序中打开了多个选择器(而不是理想的选择线程模型)以及 PollSetSelectorImpl 的实现,如此处所述