详解java nio中的select和channel

 更新时间:2019年05月28日 10:02:39   作者:爬蜥  
这篇文章主要介绍了java nio中的select和channel

什么是NIO?

线程在处理数据时,如果线程还处于将数据从channel读到buffer的这段时间内,线程可以去做别的事情,等数据都读到buffer了,线程再回来处理读到的数据

channel是什么?

类比流的概念。与流的区别在于

1.channel是可读可写的,但是一个流要么写要么读

2.chanel可以异步的读和写

3.数据总是从channel中读到buffer,或者从buffer中写到channel

流的读取或写一般是一次性的操作,数据在读取过程中不会有缓存,这也就意味着没有办法自己随便移动到想要读取的位置,要实现这个功能也就只能先缓存

java中的channel有哪些?

FileChannel:连接文件的channel,通过文件对象的getChannel方法即可获取

FileChannel的write()方法不保证一次会写到channel中的字节数;另外它不能被设置为非阻塞,永远只能设置成阻塞模式

1.DatagramChannel:处理UDP协议连接,通过DatagramChannel.open()然后再获取socket执行绑定即可端口

2.SocketChannel:它是一个已经建立连接的TCP网络socket,用来处理TCP协议连接,通过SocketChannel.open()再调用自身的connet即可建立

3.ServerSocketChannel:用来监听TCP连接的建立,通过ServerSocketChannel.open()可以建立,随后就可以绑定需要监听的端口,并等待连接的到来,每个已建立的连接都会返回一个SocketChannel

非阻塞模式下,等待连接到来的accept方法会立马返回,注意判断SocketChannel是不是null;另外可能有多个连接建立,所以监听一般会放在一个while循环里面

Buffer是什么?

用来方便操作内存块中数据的一个包装类。它有3个属性

1.capacity:表示Buffer能容纳的数据量,满了就不能再写

2.position:读或者写开始的位置

3.limit:写模式下表示能往buffer中写的数据量,最大值是capacity;读模式下表示能从buffer中获取的数据量,之前buffer中写了多少,就能读多少

从写模式转换到读模式需要用flip()完成,调用完成之后,limit会被设置成position当时的值,而positon会被设置成0;
读取数据完毕转换成写需要调用clear或者compact方法,其中clear会置position为0,limit为capacity,compact则会把原有的数据拷贝到开始的位置,然后其后的位置设置为position,limit则是capacity

mark和reset用法:在执行读取的时候,先mark住当前的位置,执行读取完成之后reset就回到原读取数据之前的位置了

怎么读取数据到多个Buffer?

创建一个数组用来放要写的数据,或者将要读到的数据,再执行读写操作即可,但是这种方式不适合读取变长消息

Buffer[] bArr = {head,body};
channel.read(bArr); //读 ,如果head本身会放自身容量的数据然后再往body中塞
Buffer[] wArr={head,body}
channel.write(wArr);//写

Selector是干啥的?

用来监控多个channel的事件,比如channel的连接建立、数据到达等等

实际上可以只用一个线程来管理所有的channel

selector使用示例

//创建selector
Selector selector = Selector.open();
//使用Selector必须设置为false,同时意味着FileChannel是不能用Selector
channel.configureBlocking(false);
// SelectionKey一共有4种值,分别代表4个事件:connect、accept、read、write
// 通过方法 interestOps 可以得到注册时对channel感兴趣的事件,具体获取方式为 interestSet & SelectionKey.OP_ACCEPT 得到的结果即是否为ACCEPT事件
//通过这种方式即实现了注册,表明当前channel需要监听的是 read 事件,如果对多个事件感兴趣,那么可以使用 SelectionKey.OP_READ | SelectionKey.OP_WRITE 方式实现
//注册方法还可以添加另一个参数,attach,用来附加更多的信息给channel,比如将Buffer给channel
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
while(true) {
//select()对channel注册的事件如果一个都没有好,那么阻塞住,返回值表示事件已经发生的chanel的个数;
//selectNow()则不阻塞,没有准备好就返回0
int readyChannels = selector.select();
if(readyChannels == 0) continue;
//用来获取准备好的channel
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if(key.isAcceptable()) {
//SeverSocketChannel接受了一个新的连接
} else if (key.isConnectable()) {
//和远程已经建立了连接
} else if (key.isReadable()) {
//channel可读
} else if (key.isWritable()) {
//channel可写
}
//必须手动执行
keyIterator.remove();
}
}

wakeup:如果channel当前刚好阻塞在select,会立马返回

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 深入讲解Java的对象头与对象组成

    深入讲解Java的对象头与对象组成

    由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头,下面这篇文章主要给大家介绍了关于Java对象头与对象组成的相关资料,需要的朋友可以参考下
    2022-02-02
  • Java字节码中jvm实例用法

    Java字节码中jvm实例用法

    在本篇文章里小编给大家整理的是一篇关于Java字节码中jvm实例用法内容,有兴趣的朋友们可以学习参考下。
    2021-02-02
  • JavaWeb开发之Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架

    JavaWeb开发之Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JC

    这篇文章主要介绍了JavaWeb开发之Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架的相关资料,需要的朋友可以参考下
    2016-12-12
  • MyBatis-Plus不使用数据库默认值的问题及解决

    MyBatis-Plus不使用数据库默认值的问题及解决

    这篇文章主要介绍了MyBatis-Plus不使用数据库默认值的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Spring和Websocket相结合实现消息的推送

    Spring和Websocket相结合实现消息的推送

    这篇文章主要介绍了Spring和Websocket相结合实现消息的推送的相关资料,本文介绍的非常详细具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-02-02
  • 详解Java中的mapstruct插件使用

    详解Java中的mapstruct插件使用

    mapstruct 的插件是专门用来处理 domin 实体类与 model 类的属性映射的,我们只需定义 mapper 接口,mapstruct 在编译的时候就会自动的帮我们实现这个映射接口,避免了麻烦复杂的映射实现,对Java mapstruct使用相关知识感兴趣的朋友一起看看吧
    2022-04-04
  • JDBC编程实现文件、图片的存储方法

    JDBC编程实现文件、图片的存储方法

    这篇文章主要介绍了JDBC编程实现文件、图片的存储方法,以实例形式分析了Java基于JDBC操作数据库的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • @Autowired 自动注入接口失败的原因及解决

    @Autowired 自动注入接口失败的原因及解决

    这篇文章主要介绍了@Autowired 自动注入接口失败的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Java String字符串和Unicode字符相互转换代码

    Java String字符串和Unicode字符相互转换代码

    这篇文章主要介绍了Java String字符串和Unicode字符相互转换代码,需要的朋友可以参考下
    2014-10-10
  • RabbitMQ 避免消息重复消费的方法

    RabbitMQ 避免消息重复消费的方法

    消费者端实现幂等性,意味着消息永远不会消费多次,即使收到了多条一样的消息,这篇文章给大家分享RabbitMQ 避免消息重复消费的方法,感兴趣的朋友一起看看吧
    2024-03-03

最新评论