返回顶部
首页 > 资讯 > 精选 >如何进行Java NIO的wakeup剖析
  • 857
分享到

如何进行Java NIO的wakeup剖析

2023-06-17 11:06:09 857人浏览 安东尼
摘要

如何进行Java NIO的wakeup剖析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java Nio的实现中,有不少细节点非常有学习意义的,就好比下面的这个点:Sele

如何进行Java NIO的wakeup剖析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

java Nio的实现中,有不少细节点非常有学习意义的,就好比下面的这个点:

Selector的 wakeup原理是什么?是如何实现的?

wakeup()

准确来说,应该是Selector的wakeup(),即Selector的唤醒,为什么要有这个唤醒操作呢?那还得从Selector的选择方式 来说明,前文已经总结过Selector的选择方式有三种:select()、select(timeout)、selectNow()。
selectNow的选择过程是非阻塞的,与wakeup没有太大关系。

select(timeout)和select()的选择过程是阻塞的,其他线程如果想终止这个过程,就可以调用wakeup来唤醒。

wakeup的原理

既然Selector阻塞式选择因为找到感兴趣事件ready才会返回(排除超时、中断),就给它构造一个感兴趣事件ready的场景即可。下图可以比较形象的形容wakeup原理:

Selector管辖的FD(文件描述符,linux即为fd,对应一个文件,windows下对应一个句柄;每个可选择Channel在创建的时 候,就生成了与其对应的FD,Channel与FD的联系见另一篇)中包含某一个FD A, A对数据可读事件感兴趣,当往图中漏斗端放入(写入)数据,数据会流进A,于是A有感兴趣事件ready,最终,select得到结果而返回。

wakeup在Selector中的定义如下:

public abstract Selector wakeup();

下面结合上图来追寻wakeup的实现:

linux下Selector默认实现为PollSelectorImpl,当内核版本大于2.6时,实现为EPollSelectorImpl,仅看这两者的wakeup方法,代码似乎完全一样:

public Selector wakeup() {     synchronized (interruptLock) {         if (!interruptTriggered) {             pollWrapper.interrupt();             interruptTriggered = true;         }     }     return this; }

window下Selector的实现为WindowsSelectorImpl,其wakeup实现如下:

public Selector wakeup() {     synchronized (interruptLock) {         if (!interruptTriggered) {             setWakeupSocket();             interruptTriggered = true;         }     }     return this; }

其中interruptTriggered为中断已触发标志,当pollWrapper.interrupt()之后,该标志即为true了;得益于这个标志,连续两次wakeup,只会有一次效果。

对比上图及上述代码,其实pollWrapper.interrupt()及setWakeupSocket()就是图中的往漏斗中倒水的过程,不 管windows也好,linux也好,它们wakeup的思想是完全一致的,不同的地方就在于实现的细节了,例如上图中漏斗与通道的链接部 分,linux下是采用管道pipe来实现的,而windows下是采用两个socket之间的通讯来实现的,它们都有这样的特性:

1)都有两个端,一个 是read端,一个是write端,windows中两个socket也是一个扮演read的角色,一个扮演write的角色;

2)当往write端写入 数据,则read端即可以收到数据;从它们的特性可以看出,它们是能够胜任这份工作的。

如果只想理解wakeup的原理,看到这里应该差不多了,不过,下面,想继续深入一下,满足更多人的好奇心。

先看看linux下PollSelector的具体wakeup实现,分阶段来介绍:

1)准备阶段

PollSelector在构造的时候,就将管道pipe,及wakeup专用FD给准备好,可以看一下它的实现:

PollSelectorImpl(SelectorProvider sp) {     super(sp, 1, 1);     int[] fdes = new int[2];     IOUtil.initPipe(fdes, false);     fd0 = fdes[0];     fd1 = fdes[1];     pollWrapper = new PollArrayWrapper(INIT_CAP);     pollWrapper.initInterrupt(fd0, fd1);     channelArray = new SelectionKeyImpl[INIT_CAP]; }

IOUtil.initPipe,采用系统调用pipe(int fd[2])来创建管道,fd[0]即为ready端,fd[1]即为write端。

另一个需要关注的点就是pollWrapper.initInterrupt(fd0, fd1),先看一下它的实现:

void initInterrupt(int fd0, int fd1) {     interruptFD = fd1;     putDescriptor(0, fd0);     putEventOps(0, POLLIN);     putReventOps(0, 0); }

以看到,initInterrupt在准备wakeup专用FD,因为fd0是read端fd,fd1是write端fd:

interruptFD被初始化为write端fd;

putDescriptor(0, fd0)初始化pollfd数组中的***个pollfd,即指PollSelector关注的***个fd,即为fd0;

putEventOps(0, POLLIN)初始化fd0对应pollfd中的events为POLLIN,即指fd0对可读事件感兴趣;

putReventOps(0, 0)只是初始化一下fd0对应的pollfd中的revents;

2)执行阶段

有了前面的准备工作,就看PollArrayWrapper中的interrupt()实现:

public void interrupt() {     interrupt(interruptFD); }

interrupt是native方法,它的入参interruptFD即为准备阶段管道的write端fd,对应于上图,其实就是漏斗端,因此,就是不看其实现,也知道它肯定扮演着倒水的这个动作,看其实现:

JNIEXPORT void JNICALL Java_sun_nio_ch_PollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd) {     int fakebuf[1];     fakebuf[0] = 1;     if (write(fd, fakebuf, 1) < 0) {          JNU_ThrowIOExceptionWithLastError(env,                                           "Write to interrupt fd failed");     } }

可以看出,interrupt(interruptFD)是往管道的write端fd1中写入一个字节(write(fd, fakebuf, 1))。

是的,只需要往fd1中写入一个字节,fd0即满足了可读事件ready,则Selector自然会因为有事件ready而中止阻塞返回。

EPollSelector与PollSelector相比,其wakeup实现就只有initInterrupt不同,它的实现如下:

void initInterrupt(int fd0, int fd1) {     outGoingInterruptFD = fd1;     incomingInterruptFD = fd0;     epollCtl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN); }

epfd之前的篇章里已经讲过,它是通过epoll_create创建出来的epoll文件fd,epollCtl调用内核epoll_ctl实现了往epfd上添加fd0,且其感兴趣事件为可读(EPOLLIN)。

因此可以断定,EPollSelector与PollSelector的wakeup实现是一致的。

因为之前一直专注与分析linux下的Java NIO实现,忽略了windows下的选择过程等,这里突然讲解其wakeup实现似乎很突兀,所以打算后面专门起一篇来介绍windows下的NIO实 现,这里我们只需要理解wakeup原理,甚至自己去看看其wakeup实现,应该也没什么难度。

关于如何进行Java NIO的wakeup剖析问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: 如何进行Java NIO的wakeup剖析

本文链接: https://lsjlt.com/news/288811.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何进行Java NIO的wakeup剖析
    如何进行Java NIO的wakeup剖析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java NIO的实现中,有不少细节点非常有学习意义的,就好比下面的这个点:Sele...
    99+
    2023-06-17
  • 如何进行VB.NET监控类的功能剖析
    这期内容当中小编将会给大家带来有关如何进行VB.NET监控类的功能剖析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。VB.NET编程语言功能强大,支持类的所有特性。每一个类实现的功能不尽相同,同时又能给我...
    99+
    2023-06-17
  • 如何进行Spring源码剖析AOP实现原理
    今天就跟大家聊聊有关如何进行Spring源码剖析AOP实现原理,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。前言前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了...
    99+
    2023-06-02
  • 如何进行java数组解析
    这期内容当中小编将会给大家带来有关如何进行java数组解析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。数组(array)是相同类型变量的集合,可以使用共同的名字引用它。数组可被定义为任何类型,可以是一维...
    99+
    2023-06-03
  • 如何进行java的io系统分析
    这篇文章将为大家详细讲解有关如何进行java的io系统分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一. Input和Output1. stream代表的是任何有能力产出数据的数据源,或...
    99+
    2023-06-03
  • 如何进行Java Mybatis中的Mapper原理分析
    如何进行Java Mybatis中的Mapper原理分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。准备1.pom文件 <depen...
    99+
    2023-06-26
  • 如何进行Java和Python的Web开发分析
    今天就跟大家聊聊有关如何进行Java和Python的Web开发分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。在Java里面有一种服务端的软件组件技术,叫做Servlet,其实它的...
    99+
    2023-06-04
  • 如何进行asmcmd的分析
    如何进行asmcmd的分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在ASM实例中,所有的存储于ASM磁盘组中的文件对于操作系统命令而言是...
    99+
    2024-04-02
  • 如何进行JDBC的分析
    这篇文章给大家介绍如何进行JDBC的分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1. 数据库编程的基础条件如果你想实现代码操作数据库,那么以下条件是你实现它的前提编程语言:例如 Java、C++、Python 等...
    99+
    2023-06-22
  • 如何进行Request的分析
    如何进行Request的分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。介绍Request类是一个http请求的类,对于爬虫而言是一个很重要的类。通常在Spider中创建这样...
    99+
    2023-06-17
  • 如何进行abstract的分析
    这篇文章将为大家详细讲解有关如何进行abstract的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。抽象类: abstract抽象:不具体,看不明白。抽象类表象体现。在不断抽取过程中,将...
    99+
    2023-06-02
  • 如何剖析TFS 2010中工作区的改进细节
    今天给大家介绍一下如何剖析TFS 2010中工作区的改进细节。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。在TFS(Team Foundation Serve...
    99+
    2023-06-17
  • VS2003 Include的垃圾问题怎么进行全面剖析
    VS2003 Include的垃圾问题怎么进行全面剖析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。希望我的一点经验能给大家带来帮助,导致VS2003 Include出错的原因...
    99+
    2023-06-17
  • 如何进行Java线程池的分析和使用
    如何进行Java线程池的分析和使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.    引言合理利用线程池能够带来三个好处。第一:降低资源...
    99+
    2023-06-25
  • 如何进行Spring MVC的解析
    这期内容当中小编将会给大家带来有关如何进行Spring MVC的解析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。MVC已经是现代Web开发中的一个很重要的部分,下面介绍一下Spring MVC的一些使用...
    99+
    2023-06-17
  • 如何进行MV-Sketch的分析
    如何进行MV-Sketch的分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。网络测量是对网络行为进行特征化、对各项指标进行量化并充分理解与正确认识互联网的最基本手段,支持...
    99+
    2023-06-03
  • 如何进行SAP CPI的分析
    本篇文章为大家展示了如何进行SAP CPI的分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。最近Jerry由于项目需要,又得学习一个新工具:SAP Cloud Platform Integrati...
    99+
    2023-06-04
  • 如何进行mysqldump单表备份加--single-transaction --master-data=2参数执行过程的内部剖析
    今天就跟大家聊聊有关如何进行mysqldump单表备份加--single-transaction --master-data=2参数执行过程的内部剖析,可能很多人都不太了解,为了让大家更加了解,小编给大家总...
    99+
    2024-04-02
  • Java NIO原理图文分析及如何用代码实现
    本篇文章为大家展示了Java NIO原理图文分析及如何用代码实现,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前言:最近在分析hadoop的RPC(Remote Procedure Call Pro...
    99+
    2023-06-17
  • 如何进行Linux命令行分析
    如何进行Linux命令行分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、命令行真的好吗程序员的使命维基百科的解释:命令行界面(英语:command-line inte...
    99+
    2023-06-28
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作