在JavaNIO反应器模式中的独立线程中调度事件处理程序

在JavaNIO反应器模式中的独立线程中调度事件处理程序,java,selector,nio,reactor,Java,Selector,Nio,Reactor,我正在使用java NIO编写一个简单的服务器应用程序,使用Reactor模式。据我所知,Reactor类负责收集事件(例如:OP_ACCEPT、OP_READ、OP_WRITE) 相对的EventHandler将负责特定的任务。因此,处理程序应该能够在单独的线程中异步运行 代码如下: 当我运行它时,它显示了一些问题,while循环保持运行,选择器保持returnreadyops集合为(1,4,16)。我猜这是因为AcceptHanndler没有以阻塞方式处理OP_ACCEPT。因此,即使从迭代

我正在使用java NIO编写一个简单的服务器应用程序,使用
Reactor模式
。据我所知,
Reactor
类负责收集
事件(例如:OP_ACCEPT、OP_READ、OP_WRITE)

相对的
EventHandler
将负责特定的任务。因此,处理程序应该能够在单独的线程中异步运行

代码如下:

当我运行它时,它显示了一些问题,while循环保持运行,
选择器保持returnreadyops集合为(1,4,16)。我猜这是因为
AcceptHanndler
没有以阻塞方式处理
OP_ACCEPT
。因此,即使从迭代器中删除键,在调用
select()
后,它也会再次显示

我不能在单独的线程中以可运行的方式运行eventHander吗


我想到了
边缘触发
水平触发
模型的概念。原因是否是因为选择器在
级别触发模式下运行?

是,选择器是级别触发的。在您的情况下,标准的工作流程如下:在检测到该通道是可接受的之后,从选择器中取消该键,并且仅在将该键传递给事件处理程序线程之后。事件处理程序线程将完成accept,1)再次注册服务器套接字以进行OP_accept;2) 根据您想要实现的协议,为OP_读取和/或OP_写入注册接受的客户端套接字。或者,您可以在主线程中完成accept(出于性能原因,如果存在大量连接客户端)

实际上,按操作类型区分线程是不可伸缩的,并且在SMP系统中,由于数据局部性差,可能会导致性能差。最好将每个客户端套接字锁定到单个线程。高性能java服务器通常是通过一个线程专门用于接受(这里只注册了一个ServerSocket)和N个工作线程用于处理客户机套接字来实现的。接受线程在循环中工作:

  • 阻塞select()直到新客户端到达
  • 完成接受
  • 选择加载最少的工作线程,并将新接受的客户端套接字的所有权转移到该线程

  • 每个工作线程都有自己的选择器和一组客户端套接字,并负责读取/写入这些套接字。

    是,选择器是级别触发的。在您的情况下,标准的工作流程如下:在检测到该通道是可接受的之后,从选择器中取消该键,并且仅在将该键传递给事件处理程序线程之后。事件处理程序线程将完成accept,1)再次注册服务器套接字以进行OP_accept;2) 根据您想要实现的协议,为OP_读取和/或OP_写入注册接受的客户端套接字。或者,您可以在主线程中完成accept(出于性能原因,如果存在大量连接客户端)

    实际上,按操作类型区分线程是不可伸缩的,并且在SMP系统中,由于数据局部性差,可能会导致性能差。最好将每个客户端套接字锁定到单个线程。高性能java服务器通常是通过一个线程专门用于接受(这里只注册了一个ServerSocket)和N个工作线程用于处理客户机套接字来实现的。接受线程在循环中工作:

  • 阻塞select()直到新客户端到达
  • 完成接受
  • 选择加载最少的工作线程,并将新接受的客户端套接字的所有权转移到该线程

  • 每个工作线程都有自己的选择器和一组客户端套接字,并负责读取/写入这些套接字。

    选择器的全部意义在于,您不必使用单独的线程。
    Selector
    的意义在于在一个线程中管理多个套接字,我没有为每个客户端使用线程。您做得比这糟糕得多。基本上,每个选择器事件都使用一个线程。您应该在当前线程中执行处理程序,并且在完成接受或读取后,或者在事件位于当前线程中的任何位置时,仅对长时间运行的事件(如数据库访问)使用辅助线程。您的基本模型已损坏..选择器的全部要点是您不必使用单独的线程。
    Selector
    的要点是在一个线程中管理多个套接字,我没有使用每个客户端的线程。您做得比这糟糕得多。基本上,每个选择器事件都使用一个线程。您应该在当前线程中执行处理程序,并且在完成接受或读取后,或者在事件位于当前线程中的任何位置时,仅对长时间运行的事件(如数据库访问)使用辅助线程。你的基本型号坏了。谢谢你的回复:D。如果选择器是
    级别触发的
    ,那么我必须在下一步
    select()
    之前完成所有事件处理程序。所以我选择的这个线程模型永远不会工作。。。实际上,我想的不是用一个线程来保存每个
    事件,我可以在每个读/写操作中使用AIO,这样它就不会保存线程,
    选择器将占用一个线程,因此它将专注于
    事件收集
    …tks,以便您回复:D。如果选择器是
    级别触发的
    ,那么我必须在下一步
    select()
    之前完成所有事件处理程序。所以我选择的这个线程模型永远不会工作。。。实际上,我想的不是用一个线程来保存每个
    事件,我可以在每个读/写操作中使用AIO,这样它就不会保存线程,
    选择器将占用一个线程,因此它将专注于
    事件收集
    。。。