NIO(非阻塞IO)

NIO(非阻塞IO)

NIO的核心三大部分
管道:Channel
缓冲区:Buffer
选择器:Selector

Buffer的三个属性
容量:(Capacity):缓冲区能够容纳的数据元素的最大值
上界:(Limit):缓冲区第一个不能读的位置
位置:(Position):下一个要被读或写的元素索引
Buffer中的几个方法
。flip();(翻动)设置为可读模式:Limit设置为Position位置
。rewind();将position重置为0,一般用于重复读
。clear();清空buffer准备再次写入
。buffer常见类型:ByteBuffer,CharBuffer,最为常用
。put,get,放入和取出数据
Channel通道
channel可以直接指定文件部分或全部映射成Buffer,channel只能跟buffer进行交互,一般需要流的getChannel()方法来初始化

Channel read=new FileInputStream.getChannle();
//读取文件到Buffer里
Channel.read();方法
FileChannel channelRead = fileInputStream.getChannel();
channelRead.read();
//写入文件到Buffer里
Channel.write();方法
FileChannel channelWriter= outputStream.getChannel();
channelWrite.write();
ByteBuffer allocate = ByteBuffer.allocate(1024);
        FileInputStream fileInputStream=new FileInputStream("a.txt");
        FileOutputStream outputStream=new FileOutputStream("b.txt");
        FileChannel channel = fileInputStream.getChannel();
        FileChannel channel1 = outputStream.getChannel();
        while (true){
            allocate.clear();
            int read = channel.read(allocate);
            if(read==-1){
                break;
            }
            allocate.flip();
            channel1.write(allocate);
        }
        channel.close();
        channel1.close();

Selector通道

选择器属性:
选择器(Selector)
。选择器类管理着一个被注册的通道集合的信息和它们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。当这么做的时候,可以选择将被激发的线程挂起,直到有就绪的的通道。
可选择通道(SelectableChannel)
。 SelectableChannel 可以被注册到 Selector 对象上,同时可以指定对那个选择器而言,那种操作是感兴趣的。一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。
选择键(SelectionKey)
。 选择键封装了特定的通道与特定的选择器的注册关系。选择键对象被SelectableChannel.register( ) 返回并提供一个表示这种注册关系的标记。选择键包含了两个比特集(以整数的形式进行编码),指示了该注册关系所关心的通道操作,以及通道已经准备好的操作。
选择器使用:
。selector使用单线程处理多个channel,当应用打开了多个channel且每个channel的吞吐量不是很大时,使用channel就比较方便。使用selector分如下的几步:

。1.创建:使用Selector selector = Selector.open()
。2.将channel注册到selector:channel.register(selector, **),该方法可返回一个SelectorKey,代表该channel在selector中的”代号”。与selector一起使用时,channel一定处于非阻塞模式下。所以需要提前设置channel.configureBlocking(false)。
。3.使用selector几个select的重载方法测试通道有多少已经准备好了:
int select()阻塞到至少有一个对象在通道上准备好了。
int select(long timeout)最长会阻塞timeout毫秒
int selectNow()不会阻塞,不管什么情况会直接返回,如果自上次调用选择操作以来,没有就绪的通道则直接返回0。
。4.调用select方法之后,如果有返回值,则说明已经有selector就绪了。此时可以通过selectedKey来选择已选择键集中就绪的通道。使用Set selectedKey = selector.selectedKeys();,之后在得到的SelectionKey的Set中可以通过SelectionKey提供的方法来操作channel。得到Channel的基本方法为selectionKey.channel() 。
为了实现Selector管理多个SocketChannel,必须将具体的SocketChannel对象注册到Selector,并声明需要监听的事件(这样Selector才知道需要记录什么数据),一共有4种事件:
1、connect:客户端连接服务端事件,对应值为SelectionKey.OP_CONNECT(8)
2、accept:服务端接收客户端连接事件,对应值为SelectionKey.OP_ACCEPT(16)
3、read:读事件,对应值为SelectionKey.OP_READ(1)
4、write:写事件,对应值为SelectionKey.OP_WRITE(4)

这个很好理解,每次请求到达服务器,都是从connect开始,connect成功后,服务端开始准备accept,准备就绪,开始读数据,并处理,最后写回数据返回。
所以,当SocketChannel有对应的事件发生时,Selector都可以观察到,并进行相应的处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值