java Nio 总结学习
来源:互联网 发布:如何用王家卫 知乎 编辑:程序博客网 时间:2024/05/16 14:00
Java Nio
三个主要接口或类
buffer
chanel
selector
一:关于buffer
ByteBuffer.allocate(size)方法确定一个buff的大小 CharBuffer
buffer.put()
向buff中写入数据 写入类型决定于是什么类型的buff
一般步骤:
1,将数据写入到 Buffer 中.
2,调用 Buffer.flip()方法, 将 NIO Buffer 转换为读模式.
3,从 Buffer 中读取数据
4,调用 Buffer.clear() 或 Buffer.compact()方法, 将 Buffer 转换为写模式.
rewind() 主要针对于读模式. 在读模式时, 读取到 limit 后, 可以调用 rewind() 方法, 将读 position 置为0.
Buffer.rewind()方法可以重置 position 的值为0, 因此我们可以重新读取/写入 Buffer 了.
多次读取某个数据 可配合使用mark()方法和reset()方法
buffer 有三个属性 position limit和capacity分别表示当前读或写的指针所在位置
二:关于chanel
chanel只能与buffer交互
chanel.read(buff) 从buff中读数据到管道中
将buff中数据循环写入管道中
while(buffer.hasRemaining()){
chanel.write(buff)//向管道中写入buff中的数据
}
chanel 管道接受数据流 从网络tcp:SocketChannel,UDP:datagramChannel,文件:FileChannel等.
SocketChannel 是一个客户端用来进行 TCP 连接的 Channel.
SocketChannel socketChannel = SocketChannel.open();// 产生一个SocketChannel
socketChannel.connect(new InetSocketAddress("http://example.com", 80));
ServerSocketChannel tcp服务端 监听某端口的socketChanel的链接
socketChannel.configureBlocking(false);// 设置channel为异步
Selector selector = Selector.open();// 创建选择器
channel.register(selector,SelectorKey.OP_READ)
注册Channel,第一个参数选择器,第二个参数指定对什么类型时间感兴趣,包含Connec,
Accept,Read,Write.
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; // 或运算,关注两种事情
三:关于Selector 选择器,选择哪个chanel处理数据
Selector selector = Selector.open();// 创建选择器
chanel注册到selector上
可以通过 Selector.select()方法获取对某件事件准备好了的 Channel, 即如果我们在注册 Channel 时, 对其的可写事件感兴趣, 那么当 select()返回时, 我们就可以获取 Channel 了.
注意, select()方法返回的值表示有多少个 Channel 可操作.如果 select()方法返回值表示有多个 Channel 准备好了, 那么我们可以通过 Selected key set 访问这个 Channel:
循环调用select()方法查看是否有channel就绪,
selector.selectedKeys() 返回可操作的事件集合
根据selectionKey 调用isAcceptable() 或isConnectable() isReadsble(),isWriteable(),等方法处理不同事件,然后移除处理完的事件keysIterator.remove();
注意, 在每次迭代时, 我们都调用 "keyIterator.remove()" 将这个 key 从迭代器中删除, 因为 select() 方法仅仅是简单地将就绪的 IO 操作放到 selectedKeys 集合中, 因此如果我们从 selectedKeys 获取到一个 key, 但是没有将它删除,
那么下一次 select 时, 这个 key 所对应的 IO 事件还在 selectedKeys 中.
Selector 的基本使用流程
1 通过 Selector.open() 打开一个 Selector.
2 将 Channel 注册到 Selector 中, 并设置需要监听的事件(interest set)
3 不断重复:
3.1 调用 select() 方法
3.2 调用 selector.selectedKeys() 获取 selected keys
3.3
迭代每个 selected key:
3.3.1 *从 selected key 中获取 对应的 Channel 和附加信息(如果有的话)
3.3.2 *判断是哪些 IO 事件已经就绪了, 然后处理它们. 如果是 OP_ACCEPT 事件, 则调用 "SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept()" 获取 SocketChannel, 并将它设置为 非阻塞的, 然后将这个 Channel 注册到 Selector 中.
3.3.4 *根据需要更改 selected key 的监听事件.
三个主要接口或类
buffer
chanel
selector
一:关于buffer
ByteBuffer.allocate(size)方法确定一个buff的大小 CharBuffer
buffer.put()
向buff中写入数据 写入类型决定于是什么类型的buff
一般步骤:
1,将数据写入到 Buffer 中.
2,调用 Buffer.flip()方法, 将 NIO Buffer 转换为读模式.
3,从 Buffer 中读取数据
4,调用 Buffer.clear() 或 Buffer.compact()方法, 将 Buffer 转换为写模式.
rewind() 主要针对于读模式. 在读模式时, 读取到 limit 后, 可以调用 rewind() 方法, 将读 position 置为0.
Buffer.rewind()方法可以重置 position 的值为0, 因此我们可以重新读取/写入 Buffer 了.
多次读取某个数据 可配合使用mark()方法和reset()方法
buffer 有三个属性 position limit和capacity分别表示当前读或写的指针所在位置
调用flip方法时,将limit属性设置为了当前的posion 限制只能读取limit个单位长度的数据
clear方法position属性设置为0,limit设置为capacity。rewind方法只是将position设置为0;
二:关于chanel
chanel只能与buffer交互
chanel.read(buff) 从buff中读数据到管道中
将buff中数据循环写入管道中
while(buffer.hasRemaining()){
chanel.write(buff)//向管道中写入buff中的数据
}
chanel 管道接受数据流 从网络tcp:SocketChannel,UDP:datagramChannel,文件:FileChannel等.
SocketChannel 是一个客户端用来进行 TCP 连接的 Channel.
SocketChannel socketChannel = SocketChannel.open();// 产生一个SocketChannel
socketChannel.connect(new InetSocketAddress("http://example.com", 80));
ServerSocketChannel tcp服务端 监听某端口的socketChanel的链接
socketChannel.configureBlocking(false);// 设置channel为异步
Selector selector = Selector.open();// 创建选择器
channel.register(selector,SelectorKey.OP_READ)
注册Channel,第一个参数选择器,第二个参数指定对什么类型时间感兴趣,包含Connec,
Accept,Read,Write.
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; // 或运算,关注两种事情
三:关于Selector 选择器,选择哪个chanel处理数据
Selector selector = Selector.open();// 创建选择器
chanel注册到selector上
可以通过 Selector.select()方法获取对某件事件准备好了的 Channel, 即如果我们在注册 Channel 时, 对其的可写事件感兴趣, 那么当 select()返回时, 我们就可以获取 Channel 了.
注意, select()方法返回的值表示有多少个 Channel 可操作.如果 select()方法返回值表示有多个 Channel 准备好了, 那么我们可以通过 Selected key set 访问这个 Channel:
循环调用select()方法查看是否有channel就绪,
selector.selectedKeys() 返回可操作的事件集合
根据selectionKey 调用isAcceptable() 或isConnectable() isReadsble(),isWriteable(),等方法处理不同事件,然后移除处理完的事件keysIterator.remove();
注意, 在每次迭代时, 我们都调用 "keyIterator.remove()" 将这个 key 从迭代器中删除, 因为 select() 方法仅仅是简单地将就绪的 IO 操作放到 selectedKeys 集合中, 因此如果我们从 selectedKeys 获取到一个 key, 但是没有将它删除,
那么下一次 select 时, 这个 key 所对应的 IO 事件还在 selectedKeys 中.
Selector 的基本使用流程
1 通过 Selector.open() 打开一个 Selector.
2 将 Channel 注册到 Selector 中, 并设置需要监听的事件(interest set)
3 不断重复:
3.1 调用 select() 方法
3.2 调用 selector.selectedKeys() 获取 selected keys
3.3
迭代每个 selected key:
3.3.1 *从 selected key 中获取 对应的 Channel 和附加信息(如果有的话)
3.3.2 *判断是哪些 IO 事件已经就绪了, 然后处理它们. 如果是 OP_ACCEPT 事件, 则调用 "SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept()" 获取 SocketChannel, 并将它设置为 非阻塞的, 然后将这个 Channel 注册到 Selector 中.
3.3.4 *根据需要更改 selected key 的监听事件.
3.3.5 *将已经处理过的 key 从 selected keys 集合中删除.
完整范例:
public class NioEchoServer { private static final int BUF_SIZE = 256; private static final int TIMEOUT = 3000; public static void main(String args[]) throws Exception { // 打开服务端 Socket ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 打开 Selector Selector selector = Selector.open(); // 服务端 Socket 监听8080端口, 并配置为非阻塞模式 serverSocketChannel.socket().bind(new InetSocketAddress(8080)); serverSocketChannel.configureBlocking(false); // 将 channel 注册到 selector 中. // 通常我们都是先注册一个 OP_ACCEPT 事件, 然后在 OP_ACCEPT 到来时, 再将这个 Channel 的 OP_READ // 注册到 Selector 中. serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { // 通过调用 select 方法, 阻塞地等待 channel I/O 可操作 if (selector.select(TIMEOUT) == 0) { System.out.print("."); continue; } // 获取 I/O 操作就绪的 SelectionKey, 通过 SelectionKey 可以知道哪些 Channel 的哪类 I/O 操作已经就绪. IteratorkeyIterator = selector.selectedKeys().iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); // 当获取一个 SelectionKey 后, 就要将它删除, 表示我们已经对这个 IO 事件进行了处理. keyIterator.remove(); if (key.isAcceptable()) { // 当 OP_ACCEPT 事件到来时, 我们就有从 ServerSocketChannel 中获取一个 SocketChannel, // 代表客户端的连接 // 注意, 在 OP_ACCEPT 事件中, 从 key.channel() 返回的 Channel 是 ServerSocketChannel. // 而在 OP_WRITE 和 OP_READ 中, 从 key.channel() 返回的是 SocketChannel. SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept(); clientChannel.configureBlocking(false); //在 OP_ACCEPT 到来时, 再将这个 Channel 的 OP_READ 注册到 Selector 中. // 注意, 这里我们如果没有设置 OP_READ 的话, 即 interest set 仍然是 OP_CONNECT 的话, 那么 select 方法会一直直接返回. clientChannel.register(key.selector(), OP_READ, ByteBuffer.allocate(BUF_SIZE)); } if (key.isReadable()) { SocketChannel clientChannel = (SocketChannel) key.channel(); ByteBuffer buf = (ByteBuffer) key.attachment(); long bytesRead = clientChannel.read(buf); if (bytesRead == -1) { clientChannel.close(); } else if (bytesRead > 0) { key.interestOps(OP_READ | SelectionKey.OP_WRITE); System.out.println("Get data length: " + bytesRead); } } if (key.isValid() && key.isWritable()) { ByteBuffer buf = (ByteBuffer) key.attachment(); buf.flip(); SocketChannel clientChannel = (SocketChannel) key.channel(); clientChannel.write(buf); if (!buf.hasRemaining()) { key.interestOps(OP_READ); } buf.compact(); } } } }}
阅读全文
0 0
- JAVA NIO 学习总结
- Java NIO 学习总结
- java Nio 总结学习
- Java NIO学习总结
- JAVA NIO 学习总结(上)
- JAVA NIO 学习总结(下)
- java nio 学习总结1
- java NIO Channel 学习总结
- Java NIO学习总结三(Selector)
- JAVA学习总结之IO/NIO概述
- java学习-NIO(五)NIO学习总结以及NIO新特性介绍
- NIO 学习总结
- Java NIO 实践经验总结
- java nio总结
- Java NIO教程总结
- Java NIO 总结
- Java NIO 简单总结
- Java nio:Buffer总结
- 7.14 将例7.13以二进制形式存放在磁盘文件中的数据读入内存,并在显示器上显示。
- Pinpoint 插件开发
- 微信支付接口
- stm32启动文件分析
- Win10连接远程桌面的时候提示您的凭证不工作
- java Nio 总结学习
- IHitTest接口
- java参数传递
- php-fpm 重启 http://www.cnblogs.com/GaZeon/p/5421906.html
- IOS开发之格式化日期时间
- Linux命令
- BZOJ1601 灌水(USACO08 Oct)
- Linux多线程实践(三)线程的基本属性设置API
- Java 类加载顺序与成员变量初始化