java bio & nio

来源:互联网 发布:shell执行python文件 编辑:程序博客网 时间:2024/04/29 16:32

简介

java bio: 同步并阻塞,基于bio的通信,Socket服务器端会发生阻塞.即在监听的过程中每次accept到一个客户端的连接,就处理这个请求,对于其他连接过来的客户端只能够阻塞等待

java nio:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器中,多路复用器轮询到链接有I/O请求的时候才启动一个线程进行处理

使用场景:

bio方式适用于连接数目比较小且固定的架构,这种方式对服务器的资源要求比较高,并发局限于应用中jdk 1.4之前

nio方式适用于链接数目多,且链接比较短(轻操作)的架构,比如聊天服务器,并且局限于应用中,jdk1.4开始支持

详解:

NIO由一个专门的线程来处理所有的IO事件,并且负责分发,事件驱动机制,事件到的时候触发,而不是同步的去监听事件,线程通讯,线程之间通过wait,notify等方式进行通讯,保证每次 上下文切换都是有意义的,减少无谓的线程切换
nio采用了双向通道的方式进行数据传输,而不是单向的流,在通道上可以注册我们感兴趣的事件,

  • SelectionKey.OP_ACCEPT(16)
  • SelectionKey.OP_CONNECT(8)
  • SelectionKey.OP_READ(1)
  • SelectionKey.OP_WRITE(4)

服务端和客户端分别维护一个管理通道的对象,我们叫做selector 该对象可以检测到一个或者多个channel上的事件,以服务端为例,如果服务端的selector上注册了读事件,某时刻客户端给服务端发送了一些数据 bio的话就会用read()方法堵塞的读取数据nio则会在服务端selector中添加一个读事件,服务端的处理线程就会轮询的访问selector,如果selector时有发现感兴趣的事件到达,就处理这些事件,如果没有感兴趣的事件到达则处理线程就会一直阻塞到感兴趣的事件到达为止

    在写nio代码的时候发现一个问题,就是在写操作之前基本从来没有对写操作进行注册

在一些流行的NIO的框架中,都能看到对OP_ACCEPT和OP_READ的处理。很少有对OP_WRITE的处理。我们经常看到的代码就是在请求处理完成后,直接通过下面的代码将结果返回给客户端:

while (bb.hasRemaining()) {    int len = socketChannel.write(bb);    if (len < 0) {     throw new EOFException();    }}

这样写在大多数的情况下都没有什么问题。但是在客户端的网络环境很糟糕的情况下,服务器会遭到很沉重的打击。
因为如果客户端的网络或者是中间交换机的问题,使得网络传输的效率很低,这时候会出现服务器已经准备好的返回结果无法通过TCP/IP层传输到客户端。这时候在执行上面这段程序的时候就会出现以下情况。

  • bb.hasRemaining()一直为true,因为服务器的返回结果已经准备好了

  • socketChannel.write(bb)的结果一直为0,不过因为网络的原因数据一直传输不过去,

  • 因为是异步非阻塞的方式,socketChannel.write(bb);不会被阻塞,立即被返回

  • 在一段时间内,这段代码会被无休止快速执行着,实际上具体什么任务都没有做,一直到网络允许当前的数据传送出去为止

这样的结果显然不是我们想要的。因此,我们对OP_WRITE也应该加以处理。在NIO中最常用的方法如下。

 while (bb.hasRemaining()) {    int len = socketChannel.write(bb);    if (len < 0){        throw new EOFException();    }    if (len == 0) {                     selectionKey.interestOps(                 selectionKey.interestOps() | SelectionKey.OP_WRITE);        mainSelector.wakeup();        break;    }}

上面的程序在网络不好的时候,将此频道的OP_WRITE操作注册到Selector上,这样,当网络恢复,频道可以继续将结果数据返回客户端的时候,Selector会通过SelectionKey来通知应用程序,再去执行写的操作。这样就能节约大量的CPU资源,使得服务器能适应各种恶劣的网络环境

0 0
原创粉丝点击