NIO
BIO 阻塞 1链接1线程 线程阻塞
线程=clone进程
IO 中断 操作内核
man 2 kernel
代码追踪命令
strace -ff -o out java Class
encode 字符转为二进制
decode 二进制转字符
核心API
●Channels
●Buffers
●Selectors
数据可以从channel 到 buffer
也可以从buffer到channel
●既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
●通道可以异步地读写。
●通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
JavaNIO channel 的实现类
●FileChannel 用于读取,写入,映射和操作文件的通道 文件通道可以安全使用多个并发线程
●DatagramChannel 面向数据报的套接字的可选通道 数据报通道可以安全使用多个并发线程。
他们支持并发读和写,但最多只有一个线程可能正在读取,并且最多一个线程可能在任何给定的时间写入。
●SocketChannel 用于面向流的连接插座的可选通道 套接字通道可以安全地被多个并发线程使用。
●ServerSocketChannel 用于面向流的侦听套接字的可选通道 服务器套接字通道可以安全地被多个并发线程使用。
Java NIO里关键的Buffer实现
●ByteBuffer
●CharBuffer
●DoubleBuffer
●FloatBuffer
●IntBuffer
●LongBuffer
●ShortBuffer
●MappedByteBuffer
Selector
Selector允许单线程处理多个 Channel
要使用Selector,得向Selector注册Channel,然后调用它的select()方法
这个方法会一直阻塞到某个注册的通道有事件就绪。
一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
Buffer的capacity,position和limit
buffer 两种模式 写 和读 双游标指针
写模式下 limit =capacity position 最大为 capacity-1
读模式下 position置0 position指针一直读取下一个可读元素并移动到下一个位置。 limit为position
分配Buffer 定义大小为48字节的buffer
ByteBuffer buf = ByteBuffer.allocate(48);
写数据到Buffer有两种方式:
●从Channel写到Buffer。 int bytesRead = inChannel.read(buf); //read into buffer.
●通过Buffer的put()方法写到Buffer里。buf.put(127)
flip()方法
flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。
clear()与compact()方法
clear 重置position指针为0 数据并未清楚后续操作将会覆盖写数据
compact 首先将剩余未读取的数据copy到buffer开头 position为剩余数据的长度
scatter / gather分散聚集
分散将channel中的数据分散写入多个buffer中
gather 聚集 将多个buffer中的数据聚齐写入channel中 scatter / gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,你可能会将消息体和消息头分散到不同的buffer中,这样你可以方便的处理消息头和消息体。 (AMQP 消息 )
Scattering Reads 分散读取
消息体必须固定大小
Java
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
分散读取 模拟AMQP消息内容
// 创建缓冲区
ByteBufferhead=ByteBuffer.allocate(4);
ByteBufferbody=ByteBuffer.allocate(8);
ByteBuffer[]bufferArr={head,body};
longbyteRead=channel.read(bufferArr);
while(byteRead!=-1){
System.out.println("byteRead:"+byteRead);
// 把数据从文件channel里读到buffer里
// 反转buffer把buffer里的数据读到后清空buffer
// buffer反转
head.flip();
body.flip();
// 检查缓冲区是否有足够的空间
while(head.hasRemaining()){
System.out.print((char)head.get());
}
while(body.hasRemaining()){
System.out.print((char)body.get());
}
System.out.println();
head.clear();
body.clear();
byteRead=channel.read(bufferArr);
}
●BIO,快递员通知你有一份快递会在今天送到某某地方,你需要在某某地方一致等待快递员的到来。
●
●NIO,快递员通知你有一份快递会送到你公司的前台,你需要每隔一段时间去前台询问是否有你的快递。
●
●AIO,快递员通知你有一份快递会送到你公司的前台,并且前台收到后会给你打电话通知你过来取。
transfer To