• Reactor线程模型


    Reactor模式

    Using Events in Highly Distributed Architectures

    Java NIO?看这一篇就够了!

    Java I/O模型从BIO到NIO和Reactor模式

    一、5种IO模型

    在《Unix网络编程》6.2节中提到了unix下可用的五种IO模型

    • 阻塞IO
    • 非阻塞IO
    • 多路复用IO(select和poll)
    • 信号驱动IO(SIGIO)
    • 异步IO(POSIX的aio_系列函数)

    1.阻塞IO模型

    最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。

      当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除阻塞状态。

      典型的阻塞IO模型的例子为:

    #如果数据没有就绪,就会一直阻塞在read方法。
    socket.read();

    2.非阻塞IO

    应用进程持续调用(轮询,polling)revfrom,来查看某个操作是否就绪。这往往会造成大量CPU时间浪费。

    3.IO多路复用

    4.信号驱动IO

    在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个SIGIO信号给用户线程,用户线程接收到信号之后,就可以在信号处理函数中调用IO读写操作来进行实际的IO请求操作。

     

    5.异步IO

      异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而从内核的角度,当它受到一个asynchronous read之后,会立刻返回,表明read请求已经成功发起了,因此不会对用户线程产生任何阻塞。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。

      也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。

    注意,异步IO是需要操作系统的底层支持,在Java 7中,提供了Asynchronous IO。

    五种IO模型的比较

    下图比较了5种不同的IO模型,可以看出,前4种的主要区别在于第一阶段,因为它们的第二阶段是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于recvfrom调用。相反,异步IO模型在这两个阶段都要处理,从而不同于其它4种模型。

    前四种IO模型实际上都不是异步的IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动式IO,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

     

    java的NIO是属于同步非阻塞IO,关于IO多路复用,java没有相应的IO模型,但有相应的编程模式,Reactor 就是基于NIO中实现多路复用的一种模式。

    二、Reactor模型

    Java大神Doug Lea在“Scalable IO in Java”中进行了归纳。

    基于Reactor Pattern 处理模式中,定义以下三种角色:

    • Reactor 将I/O事件分派给对应的Handler

    • Acceptor 处理客户端新连接,并分派请求到处理器链中

    • Handlers 执行非阻塞读/写 任务

    0.传统的BIO模型

    1.Reactor单线程模型

    2.Reactor多线程模型

    3.Reactor主从模型

    第三种模型比起第二种模型,是将Reactor分成两部分:mainReactor和subReactor。
    mainReactor负责监听server socket,接收(accept)新连接,将建立的socketChannel分派给subReactor。
    subReactor维护自己的selector, 基于mainReactor 注册的socketChannel多路分离IO读写事件,读写网络数据,对业务处理的功能,其扔给worker线程池来完成。通常,subReactor的个数可等于CPU的个数。

  • 相关阅读:
    利用数据库复制技术 实现MSSQL数据同步更新
    育子两篇你会教育自已的小孩吗
    hdu 1046 Gridland (找规律题)
    hdu 1022 Train Problem I (栈的操作,还水了半天)
    hdu 4022 Bombing (强大的map一对多的映射)
    POJ 1702 Eva's Balance (数论,平衡三进制)
    hdu 3951 Coin Game (博弈)
    hdu 1058 Humble Numbers (DP初步)
    hdu 2084 数塔 (DP初步)
    hdu 1056 HangOver (打表水题)
  • 原文地址:https://www.cnblogs.com/rouqinglangzi/p/7070962.html
Copyright © 2020-2023  润新知