文章目录一. Selector.open();二. ServerSocketChannel.open()三. serverChannel.register()四. selector.select()先回顾一下创建server与selector的过程*相当于开启一个server端并绑定为一个端口用于客户端向此发起请求*其中这个server端是非阻塞的selector帮助server端监听事件并当事件到来时处理事件 publicNIOServerDemo(intport){try{this.portport;selectorSelector.open();//创建 可选择通道并配置为非阻塞式//通过open方法创建 服务器套接字 通道ServerSocketChannel serverServerSocketChannel.open();server.configureBlocking(false);server.register(selector,SelectionKey.OP_ACCEPT);//注册感兴趣的事件server.bind(newInetSocketAddress(this.port));//绑定指定端口}catch(Exception e){e.printStackTrace();}}先从Selector的open方法开始看我们看java.nio.channels.Selector类的源码。看看open做了哪些事情一. Selector.open();open来创建SelectorselectorSelector.open();publicstaticSelectoropen()throws IOException{returnSelectorProvider.provider().openSelector();}SelectorProvider.provider() 提供默认的selectorpublicstaticSelectorProviderprovider(){synchronized(lock){//保证了整个Server程序中只有一个KQueueSelectorProvider对象if(provider!null)returnprovider;returnAccessController.doPrivileged(new PrivilegedActionSelectorProvider(){public SelectorProviderrun(){if(loadProviderFromProperty())returnprovider;if(loadProviderAsService())returnprovider;//会根据操作系统来返回不同的实现类mac平台返回KQueueSelectorProviderprovidersun.nio.ch.DefaultSelectorProvider.create();returnprovider;}});}}DefaultSelectorProvider.create默认会创建KQueueSelectorProvidermac环境下publicstaticSelectorProvidercreate(){returnnewKQueueSelectorProvider();}看看 new KQueueSelectorProvider(); 做了哪些事情KQueueSelectorImpl(SelectorProvider var1){super(var1);//关键方法longvar2IOUtil.makePipe(false);//移位处理。this.fd0(int)(var232);this.fd1(int)var2;try{this.kqueueWrappernewKQueueArrayWrapper();this.kqueueWrapper.initInterrupt(this.fd0,this.fd1);this.fdMapnewHashMap();this.totalChannels1;}catch(Throwable var8){try{FileDispatcherImpl.closeIntFD(this.fd0);}catch(IOException var7){var8.addSuppressed(var7);}try{FileDispatcherImpl.closeIntFD(this.fd1);}catch(IOException var6){var8.addSuppressed(var6);}throw var8;}}IOUtil.makePipe(true)是一个本地方法。它返回两个文件描述符高位存放的是通道read端的文件描述符低32位存放的是write端的文件描述符。longvar2IOUtil.makePipe(false);this.fd0(int)(var232);this.fd1(int)var2;把返回的pipe的write端的FD、read端的FD放在this.kqueueWrapper中后面会发现这么做是为了实现Selector的wakeup()。this.kqueueWrappernewKQueueArrayWrapper();this.kqueueWrapper.initInterrupt(this.fd0,this.fd1);二. ServerSocketChannel.open()ServerSocketChannel的实现publicstaticServerSocketChannelopen()throws IOException{returnSelectorProvider.provider().openServerSocketChannel();}public ServerSocketChannelopenServerSocketChannel()throws IOException{returnnewServerSocketChannelImpl(this);}ServerSocketChannelImpl(SelectorProvider var1)throws IOException{super(var1);this.fdNet.serverSocket(true);this.fdValIOUtil.fdVal(this.fd);this.state0;}super(var1); 中var1代表SelectorProvider而默认的SelectorProvider是KQueueSelectorProvider。 ing三. serverChannel.register()接着通过serverChannel.register(selectorSelectionKey.OP_ACCEPT)把Selector和Channel绑定在一起也就是把新建ServerSocketChannel时创建的FD与Selector绑定在一起。到此Server端已启动完成主要创建了以下对象。KQueueSelector为单例对象实际上是调用操作系统的API。KQueueSelectorImpl中包含如下内容。a. IOUtil.makePipe其实就是创建两个FD一个是read端的一个是write端的。b. initInterrupt(this.fd0, this.fd1)保存Selector上注册的FD包括pipe的write端FD和ServerSocketChannel所用的FD。四. selector.select()selector.select()主要调用了KQueueSelectorImpl的doSelectprotectedintdoSelect(longvar1)throws IOException{boolean var3false;if(this.closed){throw newClosedSelectorException();}else{this.processDeregisterQueue();intvar7;try{this.begin();var7this.kqueueWrapper.poll(var1);}finally{this.end();}this.processDeregisterQueue();returnthis.updateSelectedKeys(var7);}}this.kqueueWrapper.poll()是核心也就是轮询kqueueWrapper中保存的FD具体实现是调用native方法kevent0()。var7this.kqueueWrapper.poll(var1);intpoll(longvar1){this.updateRegistrations();intvar3this.kevent0(this.kq,this.keventArrayAddress,128,var1);returnvar3;}private nativeintkevent0(intvar1,longvar2,intvar4,longvar5);顺便看看findNative的逻辑// Invoked in the VM class linking code.staticlongfindNative(ClassLoader loader,String name){VectorNativeLibrarylibsloader!null?loader.nativeLibraries:systemNativeLibraries;synchronized(libs){intsizelibs.size();for(inti0;isize;i){NativeLibrary liblibs.elementAt(i);longentrylib.find(name);if(entry!0)returnentry;}}return0;}kevent0.()会监听kqueueWrapper中的FD有没有数据进出这会造成I/O阻塞直到有数据读写事件发生。比如由于kqueueWrapper中保存的也有ServerSocketChannel的FD所以只要ClientSocket发一份数据到ServerSocket那么kevent0()就会返回又由于kqueueWrapper中保存的也有pipe的write端的FD所以只要pipe的write端向FD发一份数据也会造成poll0()返回如果这两种情况都没有发生那么kevent0()就会一直阻塞也就是selector.select()会一直阻塞如果有任何一种情况发生那么selector.select()就会返回所以在OperationServer的run()里要用while(true)这样可以保证在Selector接收数据并处理完后继续监听poll()。KQueueSelectorImpl.wakeup()public Selectorwakeup(){synchronized(this.interruptLock){if(!this.interruptTriggered){this.kqueueWrapper.interrupt();this.interruptTriggeredtrue;}returnthis;}}wakeup()通过pipe的write端send(scoutFdbyte10)发送一个字节1来唤醒poll()的所以在需要的时候(when ing )就可以调用selector.wakeup()来唤醒Selector。参考《Netty4核心原理与手写RPC框架》
企业数字化 ERP 产品动态
相关推荐
【Nginx】nginx.conf文件结构与基础配置指令(上) /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 18:16:55
xray与fofa联动(附脚本) /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 18:15:55
虚拟环境的配置/pytorch的安装/在Jupyter notebook 添加虚拟环境 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 18:15:55
Ubuntu FreeRADIUS EAP-TLS 双向认证配置与排错 简介:面向在 Ubuntu 上搭建 802.1X EAP-TLS 双向认证测试环境的网络实验人员与运维学习者,这份文档围绕 FreeRADIUS 的部署、证书生成与终端接入验证展开,适合需要复现企业级无线认证流程的初中级读者。压缩包共 1 个 docx 文件,约… · 2026/11/3 19:41:27
深度学习在旅游推荐系统中的应用与实践 1. 项目概述 这个基于深度学习的旅游推荐系统是我在2019年完成的一个实战项目,核心思路是利用Django框架搭建Web应用,结合深度学习算法为用户提供个性化的旅游目的地推荐。当时市面上大多数旅游网站还停留在基于规则或简单协同过滤的推荐方式,… · 2026/11/3 19:41:27
FreeRADIUS EAP-TLS 双向认证与802.1X无线接入实战 简介:针对 Ubuntu 系统下用 Freeradius 搭建 802.1X EAP-TLS 双向认证测试环境编写的实操文档,面向无线网络认证初学者、企业网络运维人员以及需要验证终端证书接入的设备测试人员,可帮助解决证书签发、服务端参数配置与终端接入联调中的常见… · 2026/11/3 19:41:27
老WMS操作手册拆解:状态机、业务约束与二次开发校验 简介:《WMS系统操作手册》面向仓库管理员、供应链管理者及ERP/WMS实施与运维人员。文档围绕浙江三花智能控制股份有限公司自主开发的Web端仓储管理系统,梳理从销售订单编制、提交、审核到订单变更的完整操作路径,并覆盖主生产计划编辑、审核、… · 2026/11/3 19:41:27
SpringBoot高校健康管理系统开发实践 1. 项目背景与核心价值大学生健康管理一直是高校后勤服务的重点难点。传统纸质档案管理方式存在数据分散、更新滞后、统计分析困难等问题。我们团队开发的这套基于SpringBoot的健康管理系统,正是为了解决这些痛点而生。这个系统最核心的价值在于实现了健康数据的电子… · 2026/11/3 19:41:27
免费短链接API评测与Dub.co对接实战 1. 短链接服务与API对接的价值解析 短链接服务早已从单纯的URL缩短工具,演变为现代数字营销和数据分析的基础设施。通过将冗长的原始网址压缩成简洁的短链,不仅解决了字符限制的困扰(比如Twitter早期的140字限制),更重… · 2026/11/3 19:40:27
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46