NIO:同步非阻塞IO
BIO:同步阻塞IO
AIO:异步非阻塞IO
阻塞:要等到缓冲区中的数据准备好之后,才处理其他事情,否则一直处于等待状态
非阻塞:当我们的进程访问我们的数据缓冲区时,如果数据未准备好,则直接返回,如果数据准备好,也直接返回
(也可理解为阻塞==同步,非阻塞==异步,虽然有些不恰当)
网上大佬对阻塞和非阻塞的解释:
在阻塞模式下,若从网络流中读取不到指定大小的数据量,阻塞IO就在那里阻塞着。比如,已知后面会有10个字节的数据发过来,但是我现在只收到8个字节,那么当前线程就在那傻傻地等到下一个字节的到来,对,就在那等着,啥事也不做,直到把这10个字节读取完,这才将阻塞放开通行。
在非阻塞模式下,若从网络流中读取不到指定大小的数据量,非阻塞IO就立即通行。比如,已知后面会有10个字节的数据发过来,但是我现在只收到8个字节,那么当前线程就读取这8个字节的数据,读完后就立即返回,等另外两个字节再来的时候再去读取。
同步:某个时间段只能做一间事情.(如队列)
异步:某个时间段可以做多个事情(如多线程)
BIO---->阻塞IO(必须等到数据接收完毕才可执行业务逻辑)
----->用流传输数据(InputStream/OutputStream)用完即关闭,在用时重新开辟--浪费系统性能
----->发展---线程池
NIO----->同步非阻塞(数据传输和业务分离)
---->通过通道(Channel)和缓冲区(buffer)来传输数据,Channel(多路复用机制),避免了BIO流的重复创建和关闭对资源的消耗
------->一个线程轮询(selector选择器),数据准备完成时在去分发线程去处理
buffer缓冲区(缓冲区是双向的--->面向缓冲区)----->负责数据的存储
Channel通道(多路复用机制)--->负责链接------>负责数据的传输
selector选择器--->负责监听注册到selector的事件,进行对应的业务处理
缓冲区:负责数据的存取(本质就是数组)-->除了boolean没有缓冲区,其他7种基本数据类型都有缓冲区
通过allocate()方法获取缓冲区-->可指定大小
ByteBuffer buf=ByteBuffer.allocate(1024);
put()-->存入数据到缓冲区
get()-->从缓冲区中获取数据
四个核心属性
capacity: 容量,表示缓冲区中最大存储数据的容量,一旦声明不能改变
limit:界限,表示缓冲区可以操作数据的大小.(limit后的数据不能进行读写)
position:位置,表示缓冲区中正在操作数据的位置
0<=mark<=position<=limit<=capacity
flip()--->切换读模式
rewind()--->可重复读数据
clear()--->清空缓冲区
mark()--->标记,记录当前position的位置,可通过reset()恢复到mark的位置
hasRemaining()--->判断缓冲区中是否还有剩余的数据
remaing()--->获取缓冲区中可以操作的数量
直接缓冲区和非直接缓冲区--->通过isDirect()方法可以判断是直接缓冲区,还是非直接缓冲区
非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中
直接缓冲区:通过allocateDirect()方法分配在操作系统的物理内存中(资源消耗大)
Channel:用于源节点与目标节点的链接,channel本身不存储数据,需要配合缓冲区进行数据的传输
主要实现类:
java.nio.channels.channel
FileChannel--文件通道
SocketChannel--
ServerSocketChannel--套接字通道
DatagramChannel---UDP通道
获取通道的三种方法
1. 本地IO:
FileInputStream/FileOutputStream
RandomAccessFile
网络IO:
Socket
ServerSocket
DatagramSocket
通过getChannel()方法获取通道
2.在JDK1.7中的NIO2针对各个通道提供了静态的方法open()也可获取通道
3.在JDK1.7中的NIO2的Files工具类的newByteChannel() 也可获取通道
通道之间的数据传输
transferTo()--->直接缓冲区
transferFrom()---->直接缓冲区