javatgo 发表于 2013-1-31 01:56:46

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

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



陈皓

http://blog.csdn.net/haoel




在前些天的《Java NIO类库Selector机制解析》文章中,我们知道了下面的事情:


1)Sun的JVM在实现Selector上,在Linux和Windows平台下的细节。
2)Selector类的wakeup()方法如何唤醒阻塞在select()系统调用上的细节。


先给大家做一个简单的回顾,在Windows下,Sun的Java虚拟机在Selector.open()时会自己和自己建立loopback的TCP链接;在Linux下,Selector会创建pipe。这主要是为了Selector.wakeup()可以方便唤醒阻塞在select()系统调用上的线程(通过向自己所建立的TCP链接和管道上随便写点什么就可以唤醒阻塞线程)


我们知道,无论是建立TCP链接还是建立管道都会消耗系统资源,而在Windows上,某些Windows上的防火墙设置还可能会导致Java的Selector因为建立不起loopback的TCP链接而出现异常。


而在我的另一篇文章《用GDB调试Java程序》中介绍了另一个Java的解释器——GNU的gij,以及编译器gcj,不但可以比较高效地运行Java程序,而且还可以把Java程序直接编译成可执行文件。


GNU的之所以要重做一个Java的编译和解释器,其一个重要原因就是想解释Sun的JVM的效率和资源耗费问题。当然,GNU的Java编译/解释器并不需要考虑太多复杂的平台,他们只需要专注于Linux和衍生自Unix System V的操作系统,对于开发人员来说,离开了Windows,一切都会变得简单起来。在这里,让我们看看GNU的gij是如何解释Selector.open()和Selector.wakeup()的。


同样,我们需要一个测试程序。在这里,为了清晰,我不会例出所有的代码,我只给出我所使用的这个程序的一些关键代码。


我的这个测试程序中,和所有的Socket程序一样,下面是一个比较标准的框架,当然,这个框架应该是在一个线程中,也就是一个需要继承Runnable接口,并实现run()方法的一个类。(注意:其中的s是一个成员变量,是Selector类型,以便主线程序使用)


<div style="padding-right: 4pt; padding-left: 4pt; background: #e6e6e6; padding-bottom: 1pt; padding-top: 1pt;">

//生成一个侦听端

ServerSocketChannel ssc = ServerSocketChannel.open();
//将侦听端设为异步方式
ssc.configureBlocking(false);
//生成一个信号监视器
s = Selector.open();
//侦听端绑定到一个端口
ssc.socket().bind(new InetSocketAddress(port));
//设置侦听端所选的异步信号OP_ACCEPT
ssc.register(s,SelectionKey.OP_ACCEPT);

System.out.println("echo server has been set up ......");

while(true){
int n = s.select();

if (n == 0) { //没有指定的I/O事件发生
continue;
}
Iterator it = s.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if (key.isAcceptable()) { //侦听端信号触发

…… …… ……
…… …… ……

}
if (key.isReadable()) { //某socket可读信号
…… …… ……
…… …… ……
}
it.remove();
}
}
页: [1]
查看完整版本: Java NIO 类库Selector机制解析(续)