NIO

BIO(IO):同步并阻塞
NIO:同步并阻塞
AIO:异步非阻塞
本文主要讲解NIO。
NIO提供了除Boolean类型外的原始数据类型的缓存支持数据容器,用了多路复用技术,即一个连接并发处理多个请求。解决了传统BIO(吞吐量差、阻塞时间长)下的一个请求对应一个线程的模式。
通俗理解为NIO可做到一个线程处理多个操作,比如10000个请求来了,可用50~100个线程来处理,不用像传统IO下,必须用10000个线程处理。

NIO核心

NIO有三个重要概念,分别是缓冲区、通道、选择器。
对于NIO,通道(Channel)负责传输、缓冲区(Buffer)用于存储。
数据总是从通道读到缓冲区或从缓冲区写入通道。

Buffer

Buffer的底层是数组,可以存不同数据类型的数据,根据数据类型的不同,提供了不同的缓冲区(Boolean类型除外)
有:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer
以上缓冲区均通过

allocate() //获取缓冲区
put() //存数据到缓冲区
get() //获取缓冲区数据
flip() //将Buffer从读模式改为写模式,同时会把position设为0,limit设为写模式下的position.
rewind() //可重复从头读数据 
clear() //清空缓冲区

缓冲区有几个核心属性:

属性介绍
capacity(容量)表示缓冲区最大存储数据的容量,一旦声明不可修改
limit(界限)表示缓冲区可操作数据的大小
position(位置)表示缓冲区正在操作数据的位置
mark(标记)记录当前position的位置,可通过reset()恢复到此处

0<=mark<=position<=limit<=capacity
在写模式下,limit表示最多可往Buffer里写多少数据
在读模式下,limit下表示最多能读到多少数据
在读模式下,limit会被设置为写模式下的position.

直接缓冲区 &非直接缓冲区

直接缓冲区:allocateDirect(),将缓冲区建立在物理内存中,提高效率(只需要记住直接缓冲区提高效率,原理可以自己查一下)
非直接缓冲区:allocate(),将缓冲区建立在JVM内存中
可以用isDirect()方法查当前缓冲区是否为直接缓冲区。

缓冲区读写的步骤

1.写数据到缓冲区
2.调buffer.flip(),切换为读模式
3.从buffer读数据
4.调buffer.clear()清空缓冲区或buffer.compat()只清空已读取的数据

通道(Channel)

Channel用于源节点和目标节点之间的连接,Java NIO中,Channel负责缓冲区数据传输,Channel本身不存数据,因此要配合缓冲区进行传输。
Channel的全类名java.nio.channels.Channel
有几个实现类:
FileChannel //用于本地
SocketChannel 、ServerSocketChannel //用于TCP
DatagramChannel //用于UDP

获取channel

方1:支持通道的类都提供了getChannel()方法
本地IO:FileInputStream、FileOutputStream、RandomAccessFile
网络IO:Socket、ServerSocket、DatagramSocket
方2:JDK1.7中提供了open()方法
方3:JDK1.7的Files工具类提供了newByteChannel()

Selector(只用于网络传输中,本地没有这个概念)

用来管理被注册的通道集合的消息,与它们的就绪状态。channel与selector是一起被注册的,并用selector更新channel的就绪状态。这样,可挂起被激发的线程,直到有就绪的channel.
一个selector可监测多个channel,监测channel的读写事件是否就绪,多个channel以事件方式注册到同一个selector,使一个线程操作多个请求成为可能。selector是NIO实现非阻塞的的原因,客户端发送的channel都会注册在selector中,当读写的数据准备就绪才把请求传入服务端的一个或多个线程中,期间,这些线程可以做自己的事,直到接收到channel请求。

SelectableChannel

是所有支持就绪检查的通道的父类,SelectableChannel及其子类可被注册到selector对象上,同时可以指定对哪个选择器而言,一个通道可被注册到多个selector上。

SelectionKey

封装了特定channel于selector的注册关系,selectionKey对象被selectableChannel.register()返回并提供了一个表示这种注册关系的标记,包含两个比特集,指示了该注册关系所关心的channel操作,以及channel已经准备好的操作。
操作过程:

//a.获取selector
Selector selector =Selector.open();
//声明为非阻塞模式,只有非阻塞模式才用selector
channel.configureBlocking(false);
//b.channel注册到selector
channel.register(selector,selectionKey.OP_READ);

分散读取&聚集写入

分散读取:指从channel读数据时,将读取的数据分散到多个Buffer中。按缓冲区的顺去,将从channel读取的数据以此将Buffer写满。
聚集写入:指多个Buffer中的数据聚集到Channel,按缓冲区的顺序,写入position和limit之间数据到channel.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值