java NIO及IO模型介绍
NIO: 使用的对外内存。java nio使用的是io多路复用模型。在linux系统上,使用的是epoll系统调用。
四种IO模型:(一般在内核中进行io有两个阶段,一是内核缓冲区等待接收数据,二是内核缓冲区将数据复制到用户缓存区)
1、同步阻塞IO(BIO):用户线程调用会阻塞等待内核缓冲区的数据(如果还没有收到完整的socket数据包就会一直等待),然后将内核缓冲区的数据复制到用户缓冲区,然后内核返回结果给用户线程,用户线程解除阻塞状态。
2、同步非阻塞:用户线程调用read时,内核不管有没有数据会立即返回,然后内核执行io的2个阶段,用户线程在期间不断重试调用,直到有数据为止。缺点:耗CPU性能。
3、IO多路复用模型(java NIO):将需要read的操作的socket通道注册到Selector选择器中,再不断轮询select/epoll(阻塞)查询IO操作就绪的socket连接,收到可读连接后,通过io将用户缓冲区数据取出。
这里涉及到两步系统调用你,第一步通过select/epoll查询就绪的socket连接(即阻塞等待内核缓冲区数据),第二步调用io的read后,linux会将内核区的数据复制到用户缓冲区,通过socket连接获取用户缓冲区的数据。
优点:多路复用,一个选择器查询线程可以同时处理成千上万个channel,系统不需要创建大量的线程。选择器不断轮询获取就绪的连接,然后通过连接获取io数据这块是单独业务线程执行。
4、异步IO模型(AIO): 用户线程调用read时,内核系统会立刻返回,执行上面io的两个阶段,再给用户线程发一个信号或者回调用户线程,告知用户线程用户缓存区有数据了,用户线程就会再次获取数据。
三大组件:
Channel:通道,通道有点像流, 数据可以从Channel读到Buffer中。通过linux底层对网络io或文件io建立通道。
FileChannel,DatagramChannel,SocketChannel,ServerSocketChannel
//在和服务端连接成功之后,为了可以接收到服务端的信息,需要给通道设置读的权限。
channel.register(this.selector, SelectionKey.OP_READ);
Selector: 选择器,或是通道的管理器,管理监听多个Channel事件,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
//会一直阻塞到有一个通道在你注册的事件上就绪了
selector.select();
Buffer:缓冲区,channel通道的数据需要写入到缓冲区里,才能取出来。MappedByteBuffer内存映射文件可以读超大文件。
ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer