NIO和BIO的比较

NIO和BIO的比较

      • 1. NIO和BIO的比较
      • 2. NIO中三大组件关系
        • 2.1 Buffer
        • 2.2 Channel(通道)
        • 2.3 Buffer和Channel的注意事项和细节。
        • 2.4 Selector(选择器)

1. NIO和BIO的比较

  1. BIO以流的方式处理数据,而NIO以块的方式处理数据,块I/O的效率比流I/O高很多。
  2. BIO是阻塞的,NIO是非阻塞的
  3. BIO基于字节流和字符流进行操作,而NIO是基于Channel(通道)和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中
  4. Selector(选择器)用于监听多个通道的事件,(比如连接请求,数据到达等)因此使用单个线程就可以监听多个客户端通道。

2. NIO中三大组件关系

  1. 每个channel都会对应一个Buffer
  2. Selector都对应一个线程,一个线程对应多个channel(连接)
  3. 该图反应了有三个channel注册到该selector中
  4. 程序切换到哪个channel是由事件决定的,Event就是一个重要的概念。
  5. selector会根据不同的事件,在各个通道上切换。
  6. buffer就是一个内存块,底层有一个数组。
  7. 数据的读取写入是通过buffer,这个和BIO本质不同,BIO中要么是输入流或者是输出流,不会是双向的,而NIO中的buffer可读可写,需要flip方法切换。
  8. channel是双向的,可以返回底层操作系统的情况,如linux,底层的操作系统就是双向的

NIO和BIO的比较_第1张图片

2.1 Buffer

buffer类中的关键字段。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Su6fYMzH-1596812019735)(evernotecid://0DF43073-4D96-42B0-9702-63E240EE5CF9/appyinxiangcom/27688374/ENResource/p397)]

当执行flip函数时就会反转缓冲区。


    /**
     * Flips this buffer.  The limit is set to the current position and then
     * the position is set to zero.  If the mark is defined then it is
     * discarded.
     *
     * 

After a sequence of channel-read or put operations, invoke * this method to prepare for a sequence of channel-write or relative * get operations. For example: * *

     * buf.put(magic);    // Prepend header
     * in.read(buf);      // Read data into rest of buffer
     * buf.flip();        // Flip buffer
     * out.write(buf);    // Write header + data to channel
* *

This method is often used in conjunction with the {@link * java.nio.ByteBuffer#compact compact} method when transferring data from * one place to another.

* * @return This buffer */
public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }

然后从0重新开始读或者写,且后续的操作不能超过limit

ByteBuffer
从前面可以看出对于 Java 中的基本数据类型(boolean 除外),都有一个 Buffer 类型与之相对应,最常用的自
然是 ByteBuffer 类(二进制数据),该类的主要方法如下:
NIO和BIO的比较_第2张图片

2.2 Channel(通道)
  1. 基本介绍:NIO的通道类似于流,区别如下:
    1. 通道可以同时进行读写,而流只能读或者写
    1. 通道可以实现异步读写数据。
    1. 通道可以从缓冲读取数据,也可以写数据到缓冲
  1. BIO 中的 stream 是单向的,例如 FileInputStream 对象只能进行读取数据的操作,而 NIO 中的通道(Channel) 是双向的,可以读操作,也可以写操作。

  2. Channel 在 NIO 中是一个接口public interface Channel extends Closeable{}

  3. 常 用 的 Channel 类 有 : FileChannel 、 DatagramChannel 、 ServerSocketChannel 和 SocketChannel 。 【ServerSocketChanne 类似 ServerSocket , SocketChannel 类似 Socket】

  4. FileChannel 用于文件的数据读写,DatagramChannel 用于 UDP 的数据读写,ServerSocketChannel 和SocketChannel 用于 TCP 的数据读写。

2.3 Buffer和Channel的注意事项和细节。
  1. ByteBuffer 支持类型化的 put 和 get, put 放入的是什么数据类型,get 就应该使用相应的数据类型来取出,否则可能有 BufferUnderflowException 异常。
  2. 可以将一个普通Buffer转成只读Buffer
  3. NIO 还提供了 MappedByteBuffer, 可以让文件直接在内存(堆外的内存)中进行修改, 而如何同步到文件 由 NIO 来完成.
  4. 前面我们讲的读写操作,都是通过一个Buffer完成的,NIO还支持通过多个Buffer(即Buffer数组)完成读写操作,即Scattering和Gathering
    1. Scattering:将数据写入到 buffer 时,可以采用 buffer 数组,依次写入 [分散]
    1. Gathering: 从 buffer 读取数据时,可以采用 buffer 数组,依次读
2.4 Selector(选择器)
  1. Java的NIO,用非阻塞的IO方式,可以用一个线程处理多个的客户端连接,就会使用到 Selector(选择器)

  2. Selector 能够检测多个注册的通道上是否有事件发生(注意:多个Channel以事件的方式可以注册到同一个Selector),如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管 理多个通道,也就是管理多个连接和请求。【示意图】
    NIO和BIO的比较_第3张图片

  3. 只有在连接/通道真正有读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都 创建一个线程,不用去维护多个线程

  4. 避免了多线程之间的上下文切换导致的开销

与netty有什么关系

  1. Netty的IO线程 NioEventLoop 聚合了 Selector(选择器,也叫多路复用器),可以同时并发处理成百上千个客户端连接。
  2. 当线程从某客户端 Socket 通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。
  3. 线程通常将非阻塞IO的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道。
  4. 由于读写操作都是非阻塞的,这就可以充分提升 IO 线程的运行效率,避免由于频繁 I/O 阻塞导致的线程挂起。
  5. 一个I/O线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升

Selector、selectionKey、ServerSocketChannel和SocketChannel关系梳理图。

NIO和BIO的比较_第4张图片

  1. 当客户端连接时,会通过ServerSocketChannel得到SocketChannel
  2. 将socketChannel注册到Selector上,regist(Slector sel,int ops),一个selector上可以注册多个SocketChannel。
  3. 注册后返回一个SelectionKey,回纥该Selector关联(集合)
  4. Selector进行监听select方法,返回有事件发生通道的个数
  5. 进一步得到各个 SelectionKey (有事件发生)
  6. 再通过SelectionKey反向获取 SocketChannel,方法 channel()
  7. 可以通过 得到的 channel , 完成业务处理

你可能感兴趣的:(nettty学习,netty)