Java-NIO-Selector
目录
1 概述
Selector一般称之为选择器,也可以翻译为多路复用器。它是Java-NIO中核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。如此可实现单线程管理多个channels,也就是可以管理多个网络连接。
使用Selector的好处在于:使用更少的线程来就可以处理通道了,相比使用多个线程,避免了线程上下文切换带来的开销
2 Selector
2.1 可选择通道(SelectableChannel)
1)不是所有的Channel都能够被Selector复用的。像FileChannel就不能被选择器复用(因为它没有继承SelectableChannel).只有继承了SelectableChannel才能够被Selector复用。
2)SelectableChannel类提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。所有的socket通道,都继承了SelectableChannel类都是可选择的,包括从管道(pipe)对象中或得的通道。而FileChannel类,没有继承SelectableChannel所以不是可选择通道。
3)一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。通道和选择器之间的关系使用注册的方式完成
2.2 选择键 (SelectionKey)
1)Channel注册到后,并且一旦通道处于某种就绪的状态,就可以被选择器查询到。这个工作,使用选择器Selector的select()方法完成。select方法的作用,对感兴趣的通道操作,进行就绪状态的查询。
2)Selector可以不断查询Channel中发生的操作的就绪状态。并且挑选感兴趣的操作就绪状态。一旦通道有操作的就绪状态打成,并且是感兴趣的操作,就会被Selector选中,放进选择键集合
3)一个选择键,首先是包含了注册在Selector的通道操作的类型。也包含的特定的通道与特定的选择器之间的注册关系。
4)选择键的概念,和事件的概念比较相似。一个选择键类似于监听模式里边的一个事件。由于Selector不是事件触发的模式而是主动去查询的模式,所以不叫事件event ,而是叫SelectionKey选择键。
2.3 方法示例
-
public static void main(String[] args) throws IOException {
-
-
//创建selector
-
Selector selector = Selector.open();
-
-
//通道
-
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
-
-
//非阻塞
-
serverSocketChannel.configureBlocking(false);
-
-
//绑定连接
-
serverSocketChannel.bind(new InetSocketAddress(9999));
-
-
//将通道注册到选择器上
-
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
-
-
//查询已经就绪通道操作
-
Set<SelectionKey> selectionKeys = selector.selectedKeys();
-
//遍历集合
-
Iterator<SelectionKey> iterator = selectionKeys.iterator();
-
while (iterator.hasNext()) {
-
SelectionKey key = iterator.next();
-
//判断key就绪状态操作
-
if (key.isAcceptable()) {
-
-
}else if (key.isConnectable()){
-
-
}else if (key.isReadable()){
-
-
}else if (key.isWritable()) {
-
-
}
-
}
-
iterator.remove();
-
-
}
2.4 停止选择的方法
选择器执行选择的过程,系统底层会依次询问每个通道是否就绪,这个过程可能会造成调用线程进入阻塞状态,那么有以下方法可以唤醒select()方法中阻塞的线程
1)wakeup() 方法:通过调用Selector对象的wakeup()方法让处在阻塞状态下selector()立刻返回。该方法使得选择器上的第一个还没返回的选择操作立即返回。如果当前没有进行中的选择操作,那么下一次对selector()方法的一次调用将立即返回。
2)close()方法:通过close()方法关闭Selector。该方法使得任何一个在选择操作中阻塞的线程都被唤醒,同时使得注册到该Selector的所有Channel被注销,所有的建都会取消,但是channel本身不会关闭
3 Selector演示小demo
先启动服务端,在启动main方法
-
public static void main(String[] args) throws IOException {
-
//获取通道 绑定主机和端口号
-
SocketChannel socketChannel =
-
SocketChannel.open(new InetSocketAddress("127.0.0.1", 8080));
-
//切换到非阻塞模式
-
socketChannel.configureBlocking(false);
-
//创建buffer
-
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
-
Scanner scanner = new Scanner(System.in);
-
while (scanner.hasNext()) {
-
String str = scanner.next();
-
//写入buffer数据
-
byteBuffer.put((new Date().toString() "--->" str).getBytes());
-
//模式切换
-
byteBuffer.flip();
-
//写入通道
-
socketChannel.write(byteBuffer);
-
//关闭
-
byteBuffer.clear();
-
-
}
-
}
-
-
-
@Test
-
public void Server() throws IOException {
-
//获取服务端通道
-
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
-
-
//切换到非阻塞模式
-
serverSocketChannel.configureBlocking(false);
-
//创建buffer
-
ByteBuffer serverByteBuffer = ByteBuffer.allocate(1024);
-
//绑定端口号
-
serverSocketChannel.bind(new InetSocketAddress(8080));
-
//获取selector选择器
-
Selector selector = Selector.open();
-
//通道注册到选择器,进行监听 参数1:选择器 参数2:感兴趣的事情
-
serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
-
//选择器进行轮询 进行后续操作
-
while (selector.select() > 0 ) {
-
Set<SelectionKey> selectionKeys = selector.selectedKeys();
-
Iterator<SelectionKey> selectionKeysIterator = selectionKeys.iterator();
-
while (selectionKeysIterator.hasNext()) {
-
//查询就绪操作
-
SelectionKey next = selectionKeysIterator.next();
-
//判断什么操作
-
if (next.isAcceptable()) {
-
//获取到连接
-
SocketChannel accept = serverSocketChannel.accept();
-
//切换非阻塞模式
-
accept.configureBlocking(false);
-
//注册
-
accept.register(selector,SelectionKey.OP_READ);
-
}else if (next.isReadable()){
-
SocketChannel channel = (SocketChannel)next.channel();
-
//创建buffer
-
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
-
//读取数据
-
int length = 0;
-
while ((length = channel.read(byteBuffer)) > 0 ) {
-
byteBuffer.flip();
-
System.out.println(new String(byteBuffer.array(),0,length));
-
byteBuffer.clear();
-
}
-
-
}
-
}
-
selectionKeysIterator.remove();
-
}
-
}
在客户端输入:
服务端接收:
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgakjaa
-
第二十二篇Java NIO重点
-
Elasticsearch8 解决启动报错fatal exception while booting Elasticsearchjava.nio.file.InvalidPathException
-
Android 编译jar异常AGPBI: {“kind“:“error“,“text“:“java.nio.file.NoSuchFileException: C:\\Program Files
-
网络通信编程基础,BIO,NIO
-
Java基础:《netty3—NIO:Buffer》
-
java网络和IOBIO/NIO面试题,从Linux底层告诉你为什么Java这么设计----持续补充
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01