Java NIO

作者: jection | 来源:发表于2018-09-03 10:59 被阅读0次

    书本

    Netty权威指南
    netty实战
    O’Reilly的《Java nio》
    Unix网络编程 《unix网络编程》2卷
    Java网络编程(第4版)

    参考

    1. http://ifeve.com/java-nio-all/

    NIO(New IO)和OIO

    • nio:new io
    • oio:old io

    NIO翻译为New IO而不是Non-blocking IO,NIO不完全是非阻塞式IO(No-Blocking IO),因为其中部分通道(如FileChannel)只能运行在阻塞模式下,而其他的通道可以在阻塞式和非阻塞式之间进行选择。

    三大核心组成:

    • 通道(Channels)
    • 缓冲区(Buffers)
    • 选择器(Selectors)

    IO和NIO

    IO

    • 面向流(Stream Oriented),基于字节流和字符流进行操作的
    • 阻塞式(Blocking IO),当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。

    NIO

    • 面向缓冲区(Buffer Oriented),NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
    • 非阻塞式(No Blocking IO),线程在读写时,不用等数据全部读取或全部写完,在这之前线程可以去做其它事。
    • 选择器,Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

    使用场景:

    1. 如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,实现NIO的服务器可能是一个优势。
    2. 同样,如果你需要维持许多打开的连接到其他计算机上,如P2P网络中,使用一个单独的线程来管理你所有出站连接,可能是一个优势。
    3. 如果你有少量的连接使用非常高的带宽,一次发送大量的数据,也许典型的IO服务器实现可能非常契合。

    NIO版本

    NIO这个库是在JDK1.4中才引入的。
    目前最新的NIO版本是2.0,在jdk 7版本更新的。

    Netty版本

    最新版本4.1,听说4.x版本和3.x版本的差别极大,最好直接从4.x入手。
    对jdk的依赖:
    JDK 5 (Netty 3.x)
    JDK 6 (Netty 4.x)

    通道Channel

    • 文件通道(FileChannel)
    • UDP通道(DatagramChannel)
    • TCP客户通道(SocketChannel)
    • TCP服务通道(ServerSocketChannel)

    缓冲区Buffer

    图片.png

    8大类型

    • ByteBuffer
    • CharBuffer
    • DoubleBuffer
    • FloatBuffer
    • IntBuffer
    • LongBuffer
    • ShortBuffer
    • MappedByteBuffer

    buffer的属性

    • capacity容量,buffer的总大小/容量
    • position位置,代表读写的位置,初始状态时positon=0,position最大可为capacity – 1
    • limit最大值
      写模式,limit=capacity,表示你最多能往Buffer里写多少数据。
      读模式,limit=写模式下的position值, 表示你最多能读到多少数据。

    操作buffer

    • 初始化
      allocate()方法,初始化buffer的大小/容量(capacity)

    • 有两种写buffer的方法
      channel.read(buf),将Buffer的数据写入通道
      buf.put(127),向Buffer写入基础数据

    • 有两种读取buffer的方法
      Channel.write(buf),读取buffer的数据并写入通道
      buf.get(),从Buffer中读取数据
    • 切换
      flip(),将buffer从写模式切换到读模式,position设为0,limit设为写的最大position
    • 其他
      • rewind():重读,将position设回0,表示重头开始读buffer。
      • mark()与reset():标记,通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。
      • clear()和compact():重写,表示读完数据了,让buffer准备重新写入。
      • equals()与compareTo():比较,比较两个buffer是否一样。
    clear()和compact()区别

    clear(),实际上并未清除,只是将position设为0,limit设为 capacity
    compact(),也是准备重写写入调用方法,但是和clear有些不同,它会保留未读数据,它将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。

    equals()与compareTo()却别

    equals()当满足下列条件时,表示两个Buffer相等:
    1.有相同的类型(byte、char、int等)。
    2.Buffer中剩余的byte、char等的个数相等。
    3.Buffer中所有剩余的byte、char等都相同。

    如你所见,equals只是比较Buffer的一部分,不是每一个在它里面的元素都比较。实际上,它只比较Buffer中的剩余元素。

    compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:
    1.第一个不相等的元素小于另一个Buffer中对应的元素 。
    2.所有元素都相等,但第一个Buffer比另一个先耗尽(第一个Buffer的元素个数比另一个少)。

    Scatter/Gather

    分散Scattering Reads是指数据从一个channel读取到多个buffer中。
    聚集Gathering Writes是指数据从多个buffer写入到同一个channel。

    transferFrom()和transferTo()

    transferFrom()方法可以将数据从源通道传输到FileChannel中
    transferTo()方法将数据从FileChannel传输到其他的channel中

    选择器

    Selector允许单线程处理多个 Channel。SocketChannel开启非阻塞模式与选择器搭配,就可以实现多路复用的技术,通过将一或多个SocketChannel注册到Selector,可以询问选择器哪个通道已经准备好了读取,写入等,轮流处理各个通道注册的事件。好处是:使用一个线程就能实现多个连接通道,减少线程数和上下文切换的开销

    图片.png

    NIO写选择器(Selector.isWriteable()),如何写的问题

    参考:
    https://www.xuebuyuan.com/3206056.html

    相关文章

      网友评论

          本文标题:Java NIO

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