NIO(non-blocking)非阻塞的IO,为传统的IO提供缓存支持。
一、概述
1、Channal
Channel如同流,数据可以从channel读到buffer中,也可以从buffer读到channel中。
Channel中有:FileCannel、DatagramChannel、SocketChannel、ServerSocketChannel
2、Buffer
Buffer中有:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、ShortBuffer、LongBuffer,这8种对应java的8种基本类型。还有一个内存映射的MappedByteBuffer,是ByteBuffer的子类。
3、Selector
Selector允许单线程处理多个Channel。如果你的应用打开了多个连接(通道),但每个连 接流量很少,使用Selector就会很方便。
二、Channel
1、Channel(通道)和流:
1)数据既可以从通道中读出,也可以把数据读入到通道中,但是流是单向的
2)通道可以异步读取
3)通道的数据总是读到一个Buffer中,或者从一个Buffer读到通道中
2、Channel的实现
Channel中有:FileCannel、DatagramChannel、SocketChannel、ServerSocketChannel
FileChannel:从文件中读取数据。
DatagramChannel:能通过UDP读取网络中的数据。
SocketChannel:能通过TCP读取网络中的数据。
ServerSocketChannel:可以监听新来的TCP连接,如同WEB服务器一样。为每个新来的TCP连接创建SocketChannel。
三、Buffer
1、Buffer的基本用法
1)写入数据到Buffer,buffer会记录多少数据
2)调用flip()方法,将Buffer的写模式换成读模式,在读模式下,可以读到之前写入到buffer里面的数据。
3)从Buffer里读取数据
4)调用clear()或者compact()方法,清空buffer,clear方法是清空所有的缓存,compact是清空已读的缓存,未读的数据依然存在,新写入的数据放到未读数据的后面。
2、Buffer的三个属性capacity、position、limit
1)capacity,作为一个内存块,Buffer有固定的大小,只能往里面写capacity个byte、int等类型,若Buffer满了,需要将其清空,才可以继续写数据。
2)position,写数据的时候:position表示当前位置,初始值为0,最大值为capacity-1
读数据的时候:从某个位置读数据,当Buffer从写模式变为读模式的时候,position 会置为0,当从position处读数据的时候,position向前移动到下一个可读的位置。
3)limit,写模式:limit表示最多写多少个,limit等于capacity
读模式:limit表示最多读多少个,当buffer到读模式的时候,limit会设置成写模式的 position。
3、Buffer的常用方法
buffer的分配:allocate(capacity)
写入数据到Buffer:Channel写入(inChannel.read(buf))和buffer的put方法(bf.put(long))
flip()方法:将写模式换成读模式,将position置为0,将limit值置为position
读数据从Buffer:读数据到Channel(inChannel..write(buf))和buffer的get方法(buf.get())
rewind()方法:rewind()方法将position置为0,limit不变,重新读取数据
clear()和compact()方法:清空数据,clear()方法清空所有的,将positon置为0,limit置为capacity,compact()方法清空已读的数据,position置为未读的数据的后一位,limit置为capacity
mark()和reset()方法:mark()方法,标记一个特定的position,之后通过reset()的方法恢复到这个position。
四、Scatter/Gather
scatter和gather用于描述从Channel读取数据或者写入到Channel中去的操作。
分散(scatter)从Channel中读取是指在读操作的时候讲Channel中的数据分散然后读入到多个buffer中。
聚集(gather)写入Channel是指在写操作的时候,从多个buffer聚集到一起,然后写入到一个Channel。
ByteBuffer first = ByteBuffer.allocate(1024);
ByteBuffer second = ByteBuffer.allocate(1024);
ByteBuffer [] buffArr = {first,second};
SocketChannel channel =(SocketChannel)selectionKey.channel();
channel.read(buffArr);//分散
channel.write(buffArr);//聚集
五、通道间数据传输
1、transferFrom()
将数据从源通道传输到目的通道中。
toChannel.transferFrom(position, count, fromChannel);
2、transferTo()
将数据从FileChannel传输到其他的通道中
fromChannel.transferTo(position, count, toChannel);
六、Selector
1、Selector(选择器)是java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。Selector仅用单个线程来处理多个Channel的好处是只需要更少的线程来处理通道。
2、Selector的使用
Selector select = Selector.open()//创建Selector
channel.configureBlocking(false)//设置非阻塞
SelectionKey key = channel.register(selector,SelectionKey.OP_READ)
register可以监控4种类型的事件,Connect、Accept、Read、Write
3、SelectionKey
上面的register方法返回一个SelectionKey,SelectionKey包含interset集合、ready集合、Channel、Selector
七、ServerSocketChannel
ServerSocketChannel可以监听新进来的TCP连接的通道,想标准的IO中的ServerSocket一样。