Java NIO 知识点梳理
2018-04-06 23:37:12 0 举报
AI智能生成
Java NIO 学习后的文档记录
作者其他创作
大纲/内容
概述
chanels & buffers
不再通过字符流和字节流在设备和内存之间读写
从缓冲区写入通道,从通道读入缓冲区
非阻塞
selector
选择器同时监听多个通道事件(连接打开,数据到达)
单个线程同时监听多个通道
channel
fileChannel
文件读取数据
datagramChannel
udp读取网络数据
SocketChannel
tcp读取网络数据
ServerSocketChannel
监听新进来的TCP连接,像Web服务器那样。
对每一个新进来的连接都会创建一个SocketChannel。
Buffer
概念
是一块内存被包装成NIO Buffer对象
用于和NIO通道进行交互
属性
capicity
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。
一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
position
初始的position值为0.当一个byte、long等数据写到Buffer后,
position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
limit
写模式下,limit等于capacity
读模式下,limit等于写模式下的position
拓扑图

类型
- ByteBuffer
- MappedByteBuffer(特别)
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
Buffer类型代表了不同的数据类型,来操作缓冲区中的字节
基本用法
写入数据到Buffer
调用flip()方法
flip()方法将Buffer从写模式切换到读模式。
在读模式下,可以读取之前写入到buffer的所有数据。
从Buffer读取数据
调用clear()或者compact()
compact()
方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。
limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。
clear()
position将被设回0,limit被设置成 capacity的值。
方法
分配
allocate(int capicity)
rewind()
Buffer.rewind()将position设回0,所以你可以重读Buffer中的所有数据。limit保持不变,仍然表示能从Buffer中读取多少个元素
mark()与reset()
通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position
读写
写入到buf
channel.read(buf)
buf.put(var)
从buf读
channel.write(buf)
buf.get()
Scather/Gather
scatter
分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中
gather
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel
Selector
检测一到多个NIO通道
方法
select方法
int select()
阻塞到至少有一个通道在你注册的事件上就绪
int值表示有多少通道已经就绪。
int select(long timeout)
最长会阻塞timeout毫秒
int selectNow()
此方法执行非阻塞的选择操作。没有通道变成可选择的,则此方法直接返回零
selectedKeys()
一旦调用了select()方法,并且返回值表明有一个或更多个通道就绪了,可以通过调用selector的selectedKeys()方法,访问“已选择键集(selected key set)”中的就绪通道。如下所示:Set selectedKeys = selector.selectedKeys();
wakeUp()
唤醒select而阻塞的线程(如果当前没有,唤醒下一个)
close()
SelectionKey实例无效。通道本身并不会关闭。
创建
Selector.open()
注册通道
SelectableChannel.register()
channel.configureBlocking(false);
SelectionKey key = channel.register(selector,
Selectionkey.OP_READ);
interest集合
- Connect
- Accept
- Read
- Write
这四种事件用SelectionKey的四个常量来表示:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- SelectionKey.OP_WRITE
如果你对不止一种事件感兴趣,那么可以用“位或”操作符将常量连接起来,
如下:
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
SelectionKey
interestOps
int interestSet = selectionKey.interestOps(); |
boolean isInterestedInAccept = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT; |
boolean isInterestedInConnect = (interestSet & SelectionKey.OP_CONNECT) == SelectionKey.OP_CONNECT; |
用“位与”操作interest 集合和给定的SelectionKey常量,可以确定某个确定的事件是否在interest 集合中
readyOps
获取准备就绪的操作集合
int
readySet = selectionKey.readyOps();
selectionKey.isAcceptable();
selectionKey.isConnectable();
selectionKey.isReadable();
selectionKey.isWritable();
Channel + Selector
Channel channel = selectionKey.channel();
Selector selector = selectionKey.selector();
附加的对象
添加
SelectionKey key = channel.register(selector, SelectionKey.OP_READ, theObject);
selectionKey.attach(theObject);
获取
selectionKey.attachment()
remove
Selector不会自己从已选择键集中移除SelectionKey实例。必须在处理完通道时自己移除。下次该通道变成就绪时,Selector会再次将其放入已选择键集中。
selectedKeys.iterator().remove()
Pipe
概念
管道是2个线程之间的单向数据连接。

Pipe
有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
创建管道
Pipe pipe = Pipe.open();
写数据
访问sink通道
pipe.sink()
调用SinkChannel的
write()
sinkChannel.write(buf);
读数据
访问source通道
调用source通道的
read()
非阻塞式服务器

收藏

收藏
0 条评论
下一页