五种IO模型
在网络环境下,通俗的讲,将IO分为两步:等、数据搬迁。如果要想提高IO效率,需要将等的时间降低
五种IO模型包括:
阻塞IO
非阻塞IO
信号驱动IO
IO多路转接
异步IO(前四个被称为同步IO)
字节流和字符流
字节流:以字节为单位,每次次读入或读出是8位数据。可以读任何类型数据。
字符流:以字符为单位,每次次读入或读出是16位数据。其只能读取字符类型数据。
输出流和输入流
输出流:从内存读出到文件。只能进行写操作。
输入流:从文件读入到内存。只能进行读操作。
注意:这里的出和入,都是相对于系统内存而言的
节点流和处理流
节点流:直接与数据源相连,读入或读出。
处理流:与节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。
如果是操作二进制文件那我们就使用字节流,如果操作的是文本文件那我们就使用字符流。
尽可能的多使用处理流,这会使我们的代码更加灵活,复用性更好。
随机流:RandomAccessFile
既可以读文件,也可以写文件
可以指定位置读取(应用于多线程下载)
IO与NIO的区别
IO是面向流的,NIO是面向缓冲的
IO是阻塞的,NIO是非阻塞的
IO是单线程的,NIO 是通过选择器来模拟多线程的
NIO之Buffer(缓冲区)
标准的IO编程接口是面向字节流和字符流的。而NIO是面向通道和缓冲区的,数据总是从通道中读到buffer缓冲区内,或者从buffer缓冲区写入到通道中;( NIO中的所有I/O操作都是通过一个通道开始的。)
Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方;
Java NIO是面向缓存的I/O方法。 将数据读入缓冲器,使用通道进一步处理数据。 在NIO中,使用通道和缓冲区来处理I/O操作。
NIO之Channel(通道)
通道可以读也可以写,流一般来说是单向的(只能读或者写,所以之前我们用流进行IO操作的时候需要分别创建一个输入流和一个输出流)
通道可以异步读写
通道总是基于缓冲区Buffer来读写
通道之间的数据传输
在Java NIO中如果一个channel是FileChannel类型的,那么他可以直接把数据传输到另一个channel
NIO之Channel:Scatter / Gather
Channel 提供了一种被称为 Scatter/Gather 的新功能,也称为本地矢量 I/O。Scatter/Gather 是指在多个缓冲区上实现一个简单的 I/O 操作。正确使用 Scatter / Gather可以明显提高性能
Scatter: 从一个Channel读取的信息分散到N个缓冲区中(Buufer)
Gather: 将N个Buffer里面内容按照顺序发送到一个Channel
NIO之Selector(选择器)
Selector 一般称为选择器 ,当然你也可以翻译为 多路复用器 。它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接
使用Selector的好处在于:使用更少的线程来就可以来处理通道了,相比使用多个线程,避免了线程上下文切换带来的开销
I/O多路复用:I/O就是指的我们网络I/O,多路指多个TCP连接(或多个Channel),复用指复用一个或少量线程。串起来理解就是很多个网络I/O复用一个或少量的线程来处理这些连接
I/O复用模式下在第一个阶段大量的连接统统都可以过来直接注册到Selector复用器上面,同时只要单个或者少量的线程来循环处理这些连接事件就可以了,一旦达到“就绪”的条件,就可以立即执行真正的I/O操作。这就是I/O复用与传统的阻塞式I/O最大的不同。也正是I/O复用的精髓所在
白话解读
- Buffers:网络传输字节存放的地方。
无论是从channel中取,还是向channel中写,都必须以Buffers作为中间存贮格式
- Socket Channels:Channel是网络连接和buffer之间的数据通道。
每个连接一个channel,就像之前的socket的stream一样
- Selector:像一个巡警,在一个片区里面不停的巡逻。
一旦发现事件发生,立刻将事件select出来。不过这些事件必须是提前注册在selector上的,select出来的事件打包成SelectionKey。里面包含了事件的发生事件、地点、人物。如果警察不巡逻,每个街道(socket)分配一个警察(thread),那么一个片区有几条街道,就需要几个警察。但现在警察巡逻了,一个巡警(selector)可以管理所有的片区里面的街道(socketchannel)
以上把警察比作线程,街道比作socket或socketchannel,街道上发生的一切比作stream.把巡警比作selector,引起巡警注意的事件比作selectionKey.
从上可以看出,使用NIO可以使用一个线程,就能维护多个持久TCP连接.
文件I/O基石:Path
Java7中文件IO发生了很大的变化,专门引入了很多新的类来取代原来的基于java.io.File的文件IO操作方式
Path path = Paths.get("D:\\XMind\\bcl-java.txt");
拥抱Files类
Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法。本节教程将覆盖大部分方法。Files类包含了很多方法,所以如果本文没有提到的你也可以直接查询JavaDoc文档。
java.nio.file.Files类是和java.nio.file.Path相结合使用的
内存映射
这个功能主要是为了提高大文件的读写速度而设计的。内存映射文件(memory-mappedfile)能让你创建和修改那些大到无法读入内存的文件。有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问了。将文件的一段区域映射到内存中,比传统的文件处理速度要快很多
涉及到的类:java.nio.MappedByteBuffer
、java.nio.channels.FileChannel
BIO、NIO和AIO
BIO (
Blocking I/O
):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成NIO (
Non-blocking I/O
):同步非阻塞的I/O模型,它支持面向缓冲的,基于通道的I/O操作方法AIO (
Asynchronous I/O
):异步非阻塞的IO模型,也叫NIO2,异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作