• 什么是NIO(同步非阻塞)


    NIO的实现原理
    Java的NIO主要由三个核心部分组成:Channel、Buffer、Selector。

    基本上,所有的IO在NIO中都从一个Channel开始,数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中。Channel有好几种类型,其中比较常用的有FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel等,这些通道涵盖了UDP和TCP网络IO以及文件IO。

    Buffer本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。Java NIO里关键的Buffer实现有CharBuffer、ByteBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。这些Buffer覆盖了你能通过IO发送的基本数据类型,即byte、short、int、long、float、double、char。

    Buffer对象包含三个重要的属性,分别是capacity、position、limit,其中position和limit的含义取决于Buffer处在读模式还是写模式。但不管Buffer处在什么模式,capacity的含义总是一样的。

    capacity:作为一个内存块,Buffer有个固定的最大值,就是capacity。Buffer只能写capacity个数据,一旦Buffer满了,需要将其清空才能继续写数据往里写数据。

    position:当写数据到Buffer中时,position表示当前的位置。初始的position值为0。当一个数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity–1。当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0。当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。

    limit:在写模式下,Buffer的limit表示最多能往Buffer里写多少数据,此时limit等于capacity。当切换Buffer到读模式时, limit表示你最多能读到多少数据,此时limit会被设置成写模式下的position值。

    三个属性之间的关系,如下图所示:
    在这里插入图片描述

    Selector允许单线程处理多个 Channel,如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件例如有新连接进来,数据接收等。

    这是在一个单线程中使用一个Selector处理3个Channel的图示:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/67a9ed8752214c57a3daf5e9d599c70e.png#pic_center在这里插入图片描述

    扩展阅读

    Java NIO根据操作系统不同, 针对NIO中的Selector有不同的实现:

    macosx:KQueueSelectorProvider

    solaris:DevPollSelectorProvider

    Linux:EPollSelectorProvider (Linux kernels >= 2.6)或PollSelectorProvider

    windows:WindowsSelectorProvider

    所以不需要特别指定,Oracle JDK会自动选择合适的Selector。如果想设置特定的Selector,可以设置属性,例如: -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider。

    JDK在Linux已经默认使用epoll方式,但是JDK的epoll采用的是水平触发,所以Netty自4.0.16起, Netty为Linux通过JNI的方式提供了native socket transport。Netty重新实现了epoll机制。

    采用边缘触发方式;

    netty epoll transport暴露了更多的nio没有的配置参数,如 TCP_CORK, SO_REUSEADDR等等;

    C代码,更少GC,更少synchronized

  • 相关阅读:
    音视频云架构
    linux下通过wifi连接网络
    【安卓笔记】安卓13编译系统大包选择脚本的shell编程代码解读,巩固shell编程的知识
    CSS书写规范笔记
    基本数据类型之字符串
    ubuntu下的GDB的基本使用及CMake设置调试
    WebRTC音频预处理单元APM的整体编译及使用
    计算机竞赛 深度学习机器视觉车道线识别与检测 -自动驾驶
    (22杭电多校二)Two Permutation (dp),Package Delivery (贪心)
    java基础之final关键字[21]
  • 原文地址:https://blog.csdn.net/ebdbbd/article/details/126324318