美文网首页Java 杂谈
NIO 深入详解和重要体系分析

NIO 深入详解和重要体系分析

作者: 爱学习的蹭蹭 | 来源:发表于2019-05-12 16:33 被阅读0次

    1、Java NIO 开发的注意点

    • IntBuffer.allocate(10) 分配10个缓冲区,是一个机器生成的,不能new实例,是一个抽象类
    • SecureRandom 提供一个更为健壮的随机数
    • 服务端要将客户端的信息接收到才可以进行分发,采取HashMap将数据存储
    • NIO解决多个客户端的连接的情况,减少CPU的上下文切换的工作量,传统IO的Socket无法解决这个问题,而且多个客户端连接会启用多个线程进行通信

    2、java.nio 与 java.io

    • java.nio 在jdk1.4之后出现的包
    • java.nio 拥有3个核心概念: Selector、Channel 、Buffer,在java.nio中,我们是面向块(block)或是缓冲区(Buffer)
    • NIO的事件相当重要,用事件来判断请求与响应
    • NIO是可以存在输入流和输出流,在Buffer读到的数据也可以希尔Buffer当中(flip方法实现)状态翻转.
    • NIO的客户端与传统的Socket不同,只有一个线程进行通信,而传统的Socket编程会启动多个线程进行保证
    • configureBlocking(false); false表示设置非阻塞
    • 网络编程很多场景都是使用死循环进行实现

    • java.io 中最为核心的一个概念是流(Stream)面向流的编程,Stream是信息的载体,I/O要么是输出流,要么是输入流,不可能同时既是输入流又是输出流

    3、NIO 3个核心概念关系图如:(重点)

    • [图解关系

    • NIO 3个核心
    • S-代表Selector(Thread)

    • C-代表Channel,

    • B-代表Buffer

    • 异步最核心的原理实现是事件理念

    4、Java中有7种原生数据类型

    • Java中有7种原生数据类型都有各自对应的Buffer类型,如:IntBuffer,LongBuffer,CharBuffer等,但没有BooleanBuffer

    5、Java NIO的Selector 的 processSelectedKey 中处理了三个事件, 分别是:

    • OP_READ, 可读事件, 即 Channel 中收到了新数据可供上层读取.
    • OP_WRITE, 可写事件, 即上层可以向 Channel 写入数据.
    • OP_CONNECT, 连接建立事件, 即 TCP 连接已经建立, Channel 处于 active 状态

    6、Selector(重点)

    • Selector可以监听各种各样的事件(Event)事件当某事情发生时,连接已建立,数据已读取,读取完毕等都是事件
    • Selector通过提供者进行创建,通过系统或自定义提供者进行创建(openSelector)方法调用
    • SelectionKey 注册通道(标识事件)
    • key set (全集subset)
    • selected-key 子集(感兴趣)read与write
    • canceled-key 子集(不感兴趣)取消
    • selected-key是在进行通过添加到Selector,可以移除Set的remove方法,Inteator的remove方法
    • select方法是阻塞的
    • 每当一个Selector注册一个Channel都会SelectionKey
    • Selector一旦建立就可以对事件进行选择与注册,但不是epoll(轮询)
    • register注册到Selector对象上SelectionKey.OP_ACCEPT注册给订单ServerSocketChannel在Selector之上
    • SelectionKey.OP_ACCEPT连接事件,OP_READ读事件
    • isAcceptable月isReadble判断连接和可读数据
    • NIO的客户端的SelectionKey.OP_CONNECT连接,Executors.newSingleThreadExecutor单线程执行
    • Selector检测多个Channel,而一个线程可以被Selector控制,Channel的数据读与写由Buffer来完成

    7、Channel(重点)

    • Channel 指的是可以向其写入数据或是从中读取数据的对象,类似java.io的流(Stream)
    • 与Stream不同的是,Channel是双向的,一个流只可能是InputStream或是OutputStream,Channel打开后则可以进行读取,写入或是读写
    • Channel一定是与Buffer一起进行使用实现NIO

    8、Buffer(重点)

    • Buffer本身就是一块内存,底层实现实际上是一个数组,数据的读写是通过Buffer来实现的(重点),除了数组之外,Buffer还提供了对于数据的结构化访问方式,并且可以追踪到系统的读写过程
    • 所有数据的读写都是通过Buffer来进行的,永远不会出现直接向Channel写入数据的情况,或是直接从Channel读取数据的情况(NIO)
    • Buffer是一种容器,有特定的原生类型
    • Buffer可以做到分类进行处理

    9、关于NIO的Buffer 3个重要状态属性含义(重点

    • 图解关系
    • Buffer 3个重要状态
    • postion , limit , capacity (难点和重点)
    • 一个Buffer的capacity它包含的元素的数量,一个Buffer的capacity不可能为负数,并且永远不会变化
    • 一个Buffer的limit无法去写或读的,第一个元素的索引不可能是负数,不会超过capacity
    • 一个Buffer的position下一个元素索引的读或写不可能是负数,不会超过limit
    • 范围: capacity > limit > position
    • 范围: 0 <= mark <= position <= limit <= capacity

    10、 clear ,flip ,rewind 方法(重点)

    • clear 其实对数据重置,并没有清空数据(原理)

    11、 直接缓冲区(重点)

    • 直接缓冲区,堆的缓冲,堆上的内存分配堆内上直接由JVM管理,堆外的内存分配,不由JVM管理,有操作系统进行管理
    • DirectByteBuffer直接缓冲,用了很多不开源的底层实现
    • DirectByteBuffer在java对,就不会存在一个所谓的数组,因为真实的数据已经在堆外存放者,所以用于数据读写,直接由操作系统来跟堆外的内存进行交互(少一次数据拷贝)称为零拷贝
    • MapperByteBuffe是一个直接缓冲区,是一个内存映射文件区域,用于内存映射的文件的内存本身在java堆面,换句话说,它是堆外内存,直接从内存修改,有操作系统操作
    • 拷贝不会产生GC,由JVM控制

    12、 间接缓冲

    • 如果用了HeapBuffer实际上真正数据IO多了一个数据的拷贝过程,会把java的内存空间的字节数组的内容原封不动的拷贝到java模型内存之外的操作系统某块内存中,然后整个内存区字节跟我们IO设备进行交互

    13、 中间缓冲区

    • 对于直接缓冲区Java的JVM就可以直接本地IO的操作,避免操作系统的原生的IO还复制内容到一个中间的缓冲区

    14、 零拷贝

    • 零拷贝将IO操作时候不必你的Buffer的内容再拷贝一份放置系统的内存空间中,直接将你的堆上的分配的内存用于IO操作进行打交道,减少内存中转的过程,提供性能(重点

    15、 通过NIO读取文件涉及到3个步骤

    • 1、从FileInputStream获取到FileChannel对象
    • 2、创建Buffer
    • 3、将数据从Channel读取到Buffer中

    16、 绝对方法和相对方法的含义

    • 相当方法:limit值与position值会在操作时被考虑到
    • 绝对方法:完成忽略掉limit值与position值

    17、 ByteBuffer

    • ByteBuffer 放入是什么类型,取出来类型就是什么类型

    18、 asReadOnlyBuffer 只读缓冲区

    • 只读Buffer,我们可以随时将一个普通的Buffer调用,asReadOnlyBuffer方法返回一个只读Buffer,但不能将一个只读Buffer转换为读写Buffer

    19、 native关键字(难点)

    • native是本地的意思,通过JNI调用C / C++ 的底层代码

    20、 堆上内存(难点)

    • new 处理的实例一定位于堆上(java内存模型)native不在java内存模型,称为堆外内存(难点
    • 堆上内存有JVM管控,堆外内存由操作系统进行管理,成员变量可以访问堆内/外内存,在Buffer有一个address变量直接可以访问直接缓冲

    21、 Buffer的Scattering与Gathering(重点)

    • Scattering不仅传递一个Buffer,还可以传递一个Buffer的数组,其实将一个Channel里面的数据进行读取,如果不把第一个读完不会读第二个Channel的数据到Buffer数组
    • Gathering与Scattering刚好相反,它是写操作,一个一个地写到Buffer

    22、 CPU上下文切换会影响性能

    • 系统的CPU不断切换的变化会影响线程的性能,而且查询设计使用太多线程会有弊端

    23 推荐学习博客

    相关文章

      网友评论

        本文标题:NIO 深入详解和重要体系分析

        本文链接:https://www.haomeiwen.com/subject/jxicaqtx.html