`
feipigwang
  • 浏览: 745887 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Java NIO类库Selector机制解析(下)

阅读更多

Java NIO类库Selector机制解析(下)

赵锟   陈皓

http://blog.csdn.net/haoel

<<<<点此查看本文上篇

五、 迷惑不解 : 为什么要自己消耗资源?

令人不解的是为什么我们的JavaNew I/O要设计成这个样子?如果说老的I/O不能多路复用,如下图所示,要开N多的线程去挨个侦听每一个Channel (文件描述符) ,如果这样做很费资源,且效率不高的话。那为什么在新的I/O机制依然需要自己连接自己,而且,还是重复连接,消耗双倍的资源?

通过WEB搜索引擎没有找到为什么。只看到N多的人在报BUG,但SUN却没有任何解释。

下面一个图展示了,老的IO和新IO的在网络编程方面的差别。看起来NIO的确很好很强大。但似乎比起C/C++来说,Java的这种实现会有一些不必要的开销。

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 341.25pt; HEIGHT: 411.75pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CHAO~1.CHE%5CLOCALS~1%5CTemp%5Cmsohtml1%5C03%5Cclip_image001.png"></imagedata></shape>

六、 它山之石 : ApacheMina框架了解Selector

上面的调查没过多长时间,正好同学赵锟的一个同事也在开发网络程序,这位仁兄使用了ApacheMina框架。当我们把Mina框架的源码研读了一下后。发现在Mina中有这么一个机制:

1)Mina框架会创建一个Work对象的线程。

2)Work对象的线程的run()方法会从一个队列中拿出一堆Channel,然后使用Selector.select()方法来侦听是否有数据可以读/写。

3)最关键的是,在select的时候,如果队列有新的Channel加入,那么,Selector.select()会被唤醒,然后重新select最新的Channel集合。

4)要唤醒select方法,只需要调用Selectorwakeup()方法。

对于熟悉于系统调用的C/C++程序员来说,一个阻塞在select上的线程有以下三种方式可以被唤醒:

1) 有数据可读/写,或出现异常。

2) 阻塞时间到,即time out

3) 收到一个non-block的信号。可由killpthread_kill发出。

所以,Selector.wakeup()要唤醒阻塞的select,那么也只能通过这三种方法,其中:

1)第二种方法可以排除,因为select一旦阻塞,应无法修改其time out时间。

2)而第三种看来只能在Linux上实现,Windows上没有这种信号通知的机制。

所以,看来只有第一种方法了。再回想到为什么每个Selector.open(),在Windows会建立一对自己和自己的loopbackTCP连接;在Linux上会开一对pipepipeLinux下一般都是成对打开),估计我们能够猜得出来——那就是如果想要唤醒select,只需要朝着自己的这个loopback连接发点数据过去,于是,就可以唤醒阻塞在select上的线程了。

七、 真相大白 : 可爱的Java你太不容易了

使用Linux下的strace命令,我们可以方便地证明这一点。参看下图。图中,请注意下面几点:

1) 26654是主线程,之前我输出notify the select字符串是为了做一个标记,而不至于迷失在大量的strace log中。

2) 26662是侦听线程,也就是select阻塞的线程。

3) 图中选中的两行。26654write正是wakeup()方法的系统调用,而紧接着的就是26662epoll_wait的返回。

<shape id="_x0000_i1026" style="WIDTH: 6in; HEIGHT: 287.25pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CHAO~1.CHE%5CLOCALS~1%5CTemp%5Cmsohtml1%5C03%5Cclip_image003.png"><font face="Times New Roman" size="3"></font></imagedata></shape>

从上图可见,这和我们之前的猜想正好一样。可见,JDKSelector自己和自己建的那些TCP连接或是pipe,正是用来实现Selectornotifywakeup的功能的。

这两个方法完全是来模仿Linux中的的killpthread_kill给阻塞在select上的线程发信号的。但因为发信号这个东西并不是一个跨平台的标准(pthread_kill这个系统调用也不是所有Unix/Linux都支持的),而pipe是所有的Unix/Linux所支持的,但Windows又不支持,所以,Windows用了TCP连接来实现这个事。

关于Windows,我一直在想,Windows的防火墙的设置是不是会让Java的类似的程序执行异常呢?呵呵。如果不知道JavaSDK有这样的机制,谁知道会有多少个程序为此引起的问题度过多少个不眠之夜,尤其是Java程序员。

八、 后记

文章到这里是可以结束了,但关于Java NIOSelector引出来的其它话题还有许多,比如关于GNU Java编译器又是如何,它是否会像SunJava解释器如此做傻事?我在这里先卖一个关子,关于GNUJava编译器,我会在另外一篇文章中讲述,近期发布,敬请期待。

关于本文中所使用的实验平台如下:

· WindowsWindows XP + SP2, Sun J2SE (build 1.7.0-ea-b23)

· LinuxUbuntu 7.10 + Linux Kernel 2.6.22-14-generic, J2SE (build 1.6.0_03-b05)

本文主要的调查工作由我的大学同学赵锟完成,我帮其验证调查成果及猜想。在此也向大家介绍我的大学同学赵锟,他也是一个技术高手,在软件开发方面,特别是Unix/Linux C/C++方面有着相当的功底,相信自此以后,会有很多文章会由我和他一同发布。

本篇文章由我成文。但其全部著作权和版权归赵锟和我共同所有。我们欢迎大家转载,但希望保持整篇文章的完整性,并请勿用于任何商业用途。谢谢。

如果有任何问题,欢迎使用MSN和邮件和我联系:haoel@hotmail.com

<<<<点此查看本文上篇

 

 

(转载时请注明作者和出处。未经许可,请勿用于商业用途)

更多文章请访问我的Blog: http://blog.csdn.net/haoel

分享到:
评论

相关推荐

    Java_NIO类库Selector机制解析.doc

    Java_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.docJava_NIO类库Selector机制解析.doc

    Java-NIO类库Selector机制解析.docx

    Java_NIO类库Selector机制解析

    JavaNIO库Selector机制解析.docx

    JavaNIO库Selector机制解析.docx

    Java_NIO-Selector.rar_java nio_selector

    Java_NIO类库Selector机制解析 ,很详细 有兴趣可以下载看看。

    Java NIO——Selector机制解析三(源码分析)

    NULL 博文链接:https://goon.iteye.com/blog/1775421

    Java Nio selector例程

    java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...

    JavaNIO chm帮助文档

    Java NIO系列教程(六) Selector Java NIO系列教程(七) FileChannel Java NIO系列教程(八) SocketChannel Java NIO系列教程(九) ServerSocketChannel Java NIO系列教程(十) Java NIO DatagramChannel Java ...

    Java NIO实战开发多人聊天室

    01-Java NIO-课程简介.mp4 05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-...23-Java NIO-Selector-示例代码(客户端).mp4 24

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    Java-NIO之Selector.doc

    Java-NIO之Selector.doc

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    Java NIO Selector选择器简介.pdf

    java NIO Selector选择器简介.pdf

    Java NIO英文高清原版

    Java NIO英文高清原版

    java NIO技巧及原理

    java NIO技巧及原理解析,java IO原理,NIO框架分析,性能比较

    java NIO 中文版

    讲解了 JavaIO 与 JAVA NIO区别,JAVA NIO设计理念,以及JDK中java NIO中语法的使用

    java NIO.zip

    java NIO.zip

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    java NIO 视频教程

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    java nio中文版

    java NIO是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: – 为所有的原始类型提供 (Buffer) 缓存支持。 – 字符集编码解码解决方案。 – Channel :一个新的原始 I/O 抽象。 – 支持...

Global site tag (gtag.js) - Google Analytics