Selector SelectionKey基础学习

netty技术内幕一(Selector,SelectionKey)

Java Nio注意事项 # selector

Selector类的使用(一)

SelectionKey类的使用

/*
package java.nio.channels;import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;/**=============================================channel的多路复用器=============================================* A multiplexor of {@link SelectableChannel} objects.=============================================1个selector可以通过调用Selector#open方法创建(使用系统默认实现),也可以通过SelectorProvider#open方法提供自定义的实现。selector会一直处于打开状态,一直到调用该selector#close方法=============================================* <p> A selector may be created by invoking the {@link #open open} method of* this class, which will use the system's default {@link* java.nio.channels.spi.SelectorProvider selector provider} to* create a new selector.  A selector may also be created by invoking the* {@link java.nio.channels.spi.SelectorProvider#openSelector openSelector}* method of a custom selector provider.  A selector remains open until it is* closed via its {@link #close close} method.** <a name="ks"></a>=============================================当1个channel注册到selector时,就会得到1个SelectionKey来代表这个注册关系,1个selector维护了3个这个的SelectionKey的set集合=============================================   * <p> A selectable channel's registration with a selector is represented by a* {@link SelectionKey} object.  A selector maintains three sets of selection* keys:** <ul>=============================================第1个是 key set 集合, 它代表了注册到当前selector的所有channel注册关系, 可以通过selector#key()方法返回=============================================*   <li><p> The <i>key set</i> contains the keys representing the current*   channel registrations of this selector.  This set is returned by the*   {@link #keys() keys} method. </p></li>=============================================第2个是 selected-key set集合, 它包含了通过上一次的查询操作, 当注册在该selector上的channel的任何感兴趣的事件已就绪时, 所对应的selectionKey。 可以通过调用Selector#selectedKeys()返回这个集合永远时key set集合的子集=============================================*   <li><p> The <i>selected-key set</i> is the set of keys such that each*   key's channel was detected to be ready for at least one of the operations*   identified in the key's interest set during a prior selection operation.*   This set is returned by the {@link #selectedKeys() selectedKeys} method.*   The selected-key set is always a subset of the key set. </p></li>=============================================第3个是 cancelled-key set集合, 它代表着所有被取消的SelectionKey, 但是这些被取消的key对应的channel还没有从selector上注销, 这个集合不能直接被访问,这个集合永远时key set集合的子集=============================================*   <li><p> The <i>cancelled-key</i> set is the set of keys that have been*   cancelled but whose channels have not yet been deregistered.  This set is*   not directly accessible.  The cancelled-key set is always a subset of the*   key set. </p></li>** </ul>=============================================在新建的selector中, 这3个set集合都是空的=============================================* <p> All three sets are empty in a newly-created selector.=============================================当把1个channel注册到selector上时,就会得到1个SelectionKey来代表这个注册关系。被取消的key在查询操作期间, 才会从三个集合中移除掉。key set集合是不能被直接修改的。=============================================* <p> A key is added to a selector's key set as a side effect of registering a* channel via the channel's {@link SelectableChannel#register(Selector,int)* register} method.  Cancelled keys are removed from the key set during* selection operations.  The key set itself is not directly modifiable.=============================================无论是调用SelectionKey#cancel方法还是关闭channel, 其对应的SelectionKey都将会被添加到cancelled-key set集合中。但是这并不会使得对应channel立即从selector中注销, 而是在selector下一次作查询操作的时候, 这个channel才会从这个selector中注销, 并且注销的selectionKey将会从3个set集合中移除掉=============================================* <p> A key is added to its selector's cancelled-key set when it is cancelled,* whether by closing its channel or by invoking its {@link SelectionKey#cancel* cancel} method.  Cancelling a key will cause its channel to be deregistered* during the next selection operation, at which time the key will removed from* all of the selector's key sets.=============================================在selector的查询操作浅见, 会将发生感兴趣事件的SelectionKey添加到 slected-key 集合中,注意: 不能直接往slected-key 集合中添加SelectionKey.可以通过调用remove方法或者对应的迭代器的remove方法, 将某个selectionKey从slected-key 集合中移除=============================================* <a name="sks"></a><p> Keys are added to the selected-key set by selection* operations.  A key may be removed directly from the selected-key set by* invoking the set's {@link java.util.Set#remove(java.lang.Object) remove}* method or by invoking the {@link java.util.Iterator#remove() remove} method* of an {@link java.util.Iterator iterator} obtained from the* set.  Keys are never removed from the selected-key set in any other way;* they are not, in particular, removed as a side effect of selection* operations.  Keys may not be added directly to the selected-key set. </p>*** <a name="selop"></a>* <h2>Selection</h2>=============================================在selector的每一次查询操作期间, selectionKey可能被添加到selected-key集合当中,也可能从selected-key集合中移除,selectionKey也可能从key set集合中移除,selectionKey也可能从cancelled-key中移除。可以通过调用selector#select()、selector#select(long)、selector#selectNow()开启查询, 它包含3个步骤.=============================================* <p> During each selection operation, keys may be added to and removed from a* selector's selected-key set and may be removed from its key and* cancelled-key sets.  Selection is performed by the {@link #select()}, {@link* #select(long)}, and {@link #selectNow()} methods, and involves three steps:* </p>** <ol>=============================================第一步: cancelled-key集合中的selectionKey从3个集合中全部移除掉, 对应的channel也从selector中注销掉,这个步骤会让cancelled-key集合变为空的=============================================*   <li><p> Each key in the cancelled-key set is removed from each key set of*   which it is a member, and its channel is deregistered.  This step leaves*   the cancelled-key set empty. </p></li>=============================================第二步: 底层操作系统会去查询剩余未被注销的channel是否发生了注册时所感兴趣的事件,当1个channel的任何1个感兴趣事件已就绪时, 会执行下面2个动作中的1个=============================================*   <li><p> The underlying operating system is queried for an update as to the*   readiness of each remaining channel to perform any of the operations*   identified by its key's interest set as of the moment that the selection*   operation began.  For a channel that is ready for at least one such*   operation, one of the following two actions is performed: </p>**   <ol>=============================================如果这个channel的selectionKey还没有在selected-key集合中, 则它会被添加到这个集合中,并且该selectionKey的就绪事件集被修改为channel当前已就绪事件集。selectionKey之前的就绪集将会被丢弃。=============================================*     <li><p> If the channel's key is not already in the selected-key set then*     it is added to that set and its ready-operation set is modified to*     identify exactly those operations for which the channel is now reported*     to be ready.  Any readiness information previously recorded in the ready*     set is discarded.  </p></li>=============================================如果这个channel的selectionKey已经在selected-key集合中, 之前的就绪事件集将会保留=============================================*     <li><p> Otherwise the channel's key is already in the selected-key set,*     so its ready-operation set is modified to identify any new operations*     for which the channel is reported to be ready.  Any readiness*     information previously recorded in the ready set is preserved; in other*     words, the ready set returned by the underlying system is*     bitwise-disjoined into the key's current ready set. </p></li>**   </ol>=============================================如果selector的key set集合中的所有SelectionKey在selector查询步骤开始的时候就没有任何感兴趣的事件,那么就不会更新selected-key集合, 也不会更新selectionKey中的任何就绪事件集=============================================*   If all of the keys in the key set at the start of this step have empty*   interest sets then neither the selected-key set nor any of the keys'*   ready-operation sets will be updated.=============================================如果每个key都被添加到了cacelled-key集合中, 那在第一步的时候就已经清空了=============================================*   <li><p> If any keys were added to the cancelled-key set while step (2) was*   in progress then they are processed as in step (1). </p></li>** </ol>=============================================是等待1个channel感兴趣的事件就绪, 还是等待多个channel感兴趣的事件就绪, 等待多长时间是selector查询操作的这3个方法的区别=============================================   * <p> Whether or not a selection operation blocks to wait for one or more* channels to become ready, and if so for how long, is the only essential* difference between the three selection methods. </p>*** <h2>Concurrency</h2>=============================================Selectors本身是线程安全的,但是他们的key set集合不是线程安全的=============================================   * <p> Selectors are themselves safe for use by multiple concurrent threads;* their key sets, however, are not.* <p> The selection operations synchronize on the selector itself, on the key* set, and on the selected-key set, in that order.  They also synchronize on* the cancelled-key set during steps (1) and (3) above.=============================================对selectionKey的感兴趣事件进行修改,不会立即生效,它将会在下一次查询操作时才会生效=============================================   * <p> Changes made to the interest sets of a selector's keys while a* selection operation is in progress have no effect upon that operation; they* will be seen by the next selection operation.=============================================key可能会在任何事件取消, channnel也可能在任何时间被关闭。因此,从selector中获取的key set集合并不意味着这些key都是有效的或者这些key对应的channel都是打开状态的,应用代码应该同步并且在必要的时候检查它们的状态, 以确定它们是否被取消或者被关闭了=============================================   * <p> Keys may be cancelled and channels may be closed at any time.  Hence the* presence of a key in one or more of a selector's key sets does not imply* that the key is valid or that its channel is open.  Application code should* be careful to synchronize and check these conditions as necessary if there* is any possibility that another thread will cancel a key or close a channel.=============================================1个线程调用selector#select()或者selector#select(long)方法可以通过其它线程使用以下的方式中断: =============================================   * <p> A thread blocked in one of the {@link #select()} or {@link* #select(long)} methods may be interrupted by some other thread in one of* three ways:** <ul>=============================================通过调用selector的wakeup方法=============================================   *   <li><p> By invoking the selector's {@link #wakeup wakeup} method,*   </p></li>=============================================通过调用selector的close方法=============================================   *   <li><p> By invoking the selector's {@link #close close} method, or*   </p></li>=============================================通过调用阻塞线程对象的interrupt方法, 在这种情况下, 线程会设置中断标记, 并且selector的wakeup()方法将会被调用=============================================   *   <li><p> By invoking the blocked thread's {@link*   java.lang.Thread#interrupt() interrupt} method, in which case its*   interrupt status will be set and the selector's {@link #wakeup wakeup}*   method will be invoked. </p></li>** </ul>* <p> The {@link #close close} method synchronizes on the selector and all* three key sets in the same order as in a selection operation.** <a name="ksc"></a>=============================================selector的key set集合与selected-key集合通常对多线程并发来说不是安全的。如果1个线程要直接修改这些set集合,应当要对这些set集合本身同步加锁。如果这个set集合在获取迭代器后,以任何除了调用迭代器本身的remove的方法修改了,那么会抛出并发修改异常,=============================================   	* <p> A selector's key and selected-key sets are not, in general, safe for use* by multiple concurrent threads.  If such a thread might modify one of these* sets directly then access should be controlled by synchronizing on the set* itself.  The iterators returned by these sets' {@link* java.util.Set#iterator() iterator} methods are <i>fail-fast:</i> If the set* is modified after the iterator is created, in any way except by invoking the* iterator's own {@link java.util.Iterator#remove() remove} method, then a* {@link java.util.ConcurrentModificationException} will be thrown. </p>**** @see SelectableChannel* @see SelectionKey*/public abstract class Selector implements Closeable {protected Selector() { }public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();}// 返回 selector是否处于打开状态public abstract boolean isOpen();public abstract SelectorProvider provider();// 返回 selector的key set集合(注册的所有channel对应的SelectionKey)public abstract Set<SelectionKey> keys();// 返回 selector的key set集合(注册的所有channel对应的SelectionKey)public abstract Set<SelectionKey> selectedKeys();// 查询selector当前注册的channel感兴趣且已就绪的事件// 这个方法是非阻塞的。如果当前没有已就绪的事件,则返回0。// 调用此方法会消耗1次wakeup方法的调用public abstract int selectNow() throws IOException;// 查询selector当前注册的channel感兴趣且已就绪的事件// 这个方法是阻塞的,它会在如下的几种情况下停止阻塞:// 		1. 查询到至少1个channel的感兴趣且已就绪事件//      2. 调用了selector#wakeup方法//      3. 当前线程被中断//      4. 已过超时时间// 这个方法并不保证时间是对的,会有毫秒上的差异。// 指定的时间不应当为负数。如果是0,表示超时时间无限长。public abstract int select(long timeout) throws IOException;// 查询selector当前注册的channel感兴趣且已就绪的事件// 这个方法是阻塞的,它会在如下的几种情况下停止阻塞:// 		1. 查询到至少1个channel的感兴趣且已就绪事件//      2. 调用了selector#wakeup方法//      3. 当前线程被中断public abstract int select() throws IOException;// 调用此方法能让正处于查询状态的selector立即唤醒返回// 如果selector调用了select()或者select(long)处于阻塞状态, 调用此方法会让select方法立即返回。// 如果selector还未调用select()或者select(long)或者selectNow()前,就已经调用了wakeup,// 那么下一次调用这三个方法中的任何一个时,将会立即返回。// 在2个select()期间,调用此方法2次或多次,跟调用1次是一样的。// 作用类似于LockSupport#unpark()中的许可证。public abstract Selector wakeup();// 关闭selector// 如果selector正在select查询阻塞状态,那么它会停止阻塞,类似于调用了wakeup方法。// 任何未被取消的SelectionKey将会失效,对应的channnel也会注销掉,与此selector关联的其它资源也会被释放掉。// 再次调用此方法没有任何效果。// 关闭此selector后,除了调用wakeup方法外,调用任何其它的方法都将会抛出异常。public abstract void close() throws IOException;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/191552.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试就是这么简单,offer拿到手软(一)—— 常见非技术问题回答思路

面试系列&#xff1a; 面试就是这么简单&#xff0c;offer拿到手软&#xff08;一&#xff09;—— 常见非技术问题回答思路 面试就是这么简单&#xff0c;offer拿到手软&#xff08;二&#xff09;—— 常见65道非技术面试问题 文章目录 一、前言二、常见面试问题回答思路问…

cyclictest 交叉编译与使用

目录 使用版本问题编译 numactl编译 cyclictest使用参考 cyclictest 主要是用于测试系统延时&#xff0c;进而判断系统的实时性 使用版本 rt-tests-2.6.tar.gz numactl v2.0.16 问题 编译时&#xff0c;需要先编译 numactl &#xff0c;不然会有以下报错&#xff1a; arm-…

在 Linux 中使用 udev 规则固定摄像头节点

简介 通过编写 udev 规则来固定 USB 摄像头节点&#xff0c;以便在系统中始终使用相同的设备路径访问摄像头。 确定摄像头的供应商 ID 和产品 ID 使用 lsusb 命令确定连接的 USB 摄像头的供应商 ID 和产品 ID。示例命令及输出&#xff1a; $ lsusb Bus 001 Device 030: ID 220…

AI 绘画 | Stable Diffusion 电商模特

前言 上一篇文章讲到如何给人物更换背景和服装。今天主要讲电商模特,就是服装电商们的固定服装产品图片如何变成真人模特穿上的固定服装产品效果图。如果你掌握了 《AI 绘画 | Stable Diffusion 人物 换背景|换服装》,这篇文章对你来说,上手会更轻松。 教程 提取服装蒙版…

Java实现简单飞翔小鸟游戏

一、创建新项目 首先创建一个新的项目&#xff0c;并命名为飞翔的鸟。 其次在飞翔的鸟项目下创建一个名为images的文件夹用来存放游戏相关图片。 用到的图片如下&#xff1a;0~7&#xff1a; bg&#xff1a; column&#xff1a; gameover&#xff1a; ground&#xff1a; st…

记QListWidget中QPushButton QSS样式失效的“bug”

一、场景 有一个QListWidget的列表&#xff1b;里面存放了若干QListWidgetItem&#xff1b;每个QListWidgetItem与一个自定义类对象绑定——通过QListWidget的setItemWidget()实现。自定义对象继承于QWidget&#xff0c;且内含QPushButton。 二、bug描述 在该QListWidget的外…

Mybatis 分页查询的三种实现

Mybatis 分页查询 1. 直接在 sql 中使用 limit2. 使用 RowBounds3. 使用 Mybatis 提供的拦截器机制3.1 创建一个自定义拦截器类实现 Interceptor3.2 创建分页查询函数 与 sql3.3 编写拦截逻辑3.4 注册 PageInterceptor 到 Mybatis 拦截器链中3.5 测试 准备一个分页查询类 Data…

Clion调试QTQString看不到值问题处理

环境 Clion &#xff1a;2019.3.6 Qt &#xff1a;5.9.6&#xff08;MinGW&#xff09; 环境搭建参考&#xff1a;https://blog.csdn.net/qq_27953479/article/details/132338745 调试时QString看不到值问题处理 下载文件 qt.py : https://github.com/KDE/kdevelop/blob/…

CIS|安森美微光近红外增强相机论文解析

引言 在之前的文章中&#xff0c;我们介绍了索尼、安森美以及三星等Sensor厂家在车载领域中的技术论文&#xff0c;分析了各个厂家不同的技术路线、Sensor架构以及差异点。今天&#xff0c;笔者借豪威科技在移动端200Mega Pixels产品的技术论文&#xff0c;讲解消费级CIS传感器…

高级软件工程15本书籍

如果您想学习软件工程技能并提高您的专业知识&#xff0c;那么这里是您的最佳选择。我们有一本很棒的书&#xff0c;可以极大地增强您在软件工程方面的知识。 1&#xff09;干净的代码 Robert C. Martin 写了一本名为“干净代码&#xff1a;敏捷软件工艺手册”的书。在本书中&…

如何在WordPress中批量替换图片路径?

很多站长在使用WordPress博客或者搬家时&#xff0c;需要把WordPress文章中的图片路径进行替换来解决图片不显示的问题。总结一下WordPress图片路径批量替换的过程&#xff0c;方便有此类需求的站长们学习。 什么情况下批量替换图片路径 1、更换了网站域名 有许多网站建设初期…

面试 Java 基础八股文十问十答第二期

面试 Java 基础八股文十问十答第二期 作者&#xff1a;程序员小白条 ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 11.什么是反射&#xff1f;反射有哪些作用&#xff1f;反射在Sping中的体现 (1): 什么是反射? 反射可以在运行时获取到一个类的所有信息&#xff0c;包括(成员变量&am…

关于qiankun沙箱sandbox(面试题)

为什么要有js资源隔离机制&#xff1f; 主应用和子应用&#xff0c;相同的全局变量&#xff0c;可能会发生冲突&#xff0c;子应用和子应用之间&#xff0c;相同的全局变量&#xff0c;也可能会发生冲突。在这里我们主要指的就是window。 思路&#xff1a;打开沙箱时能够修改…

Spring中@Transactional注解

在Spring框架中&#xff0c;Transactional 是一个注解&#xff0c;用于声明事务性的方法。这个注解可以被应用在方法级别或类级别上。它提供了一种声明式的事务管理方式&#xff0c;避免了在代码中直接编写事务管理相关的代码。Transactional 注解能够将一个方法纳入到一个事务…

基于SSM的生鲜在线销售系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

亚马逊云科技推出新一代自研芯片

北京——2023 年12月1日 亚马逊云科技在2023 re:Invent全球大会上宣布其自研芯片家族的两个系列推出新一代&#xff0c;包括Amazon Graviton4和Amazon Trainium2&#xff0c;为机器学习&#xff08;ML&#xff09;训练和生成式人工智能&#xff08;AI&#xff09;应用等广泛的工…

Linux: 退出vim编辑模式

一、使用快捷键进行退出 1、按“Esc”键进入命令模式 当我们在vim编辑模式下输入完毕需要进行退出操作时&#xff0c;首先需要按下“Esc”键&#xff0c;将vim编辑器从插入模式或者替换模式切换到命令模式。 ESC 2、输入“:wq”保存并退出 在命令模式下&#xff0c;输入“:…

锐捷RG-UAC应用网关 前台RCE漏洞复现

0x01 产品简介 锐捷RG-UAC系列应用管理网关是锐捷自主研发的应用管理产品。 0x02 漏洞概述 锐捷RG-UAC应用管理网关 nmc_sync.php 接口处存在命令执行漏洞&#xff0c;未经身份认证的攻击者可执行任意命令控制服务器权限。 0x03 复现环境 FOFA&#xff1a;app"Ruijie-R…

JavaWeb | JavaScript基础

目录: 1.JavaScript简介2.JavaScript注释3.JavaScript语法 :变量的定义函数的定义 4.JavaScript内置对象4.1 window的作用 &#xff1a;出现提示框打开关闭窗口定时器 4.2 history的作用4.3 document的作用 &#xff1a;在网页上输出设置网页属性访问文档元素&#xff0c;特别是…

jni子线程回调java实例

背景 最近有项目需求&#xff0c;需要在jni中创建多个子线程&#xff0c;并在子线程中&#xff0c;回调java将byte[]数据上报给java处理 demo实例 关键代码 static jmethodID method_callback; jclass global_class NULL; jclass myClass NULL; JavaVM* gJavaVM NULL;ji…