http://blog.csdn.net/hsuxu/article/details/9876983java
以前强调这么多关于linux内核的poll及epoll,无非是想让你们先有个认识:
Java NIO中的选择器依赖操做系统内核的这些系统调用,咱们这里只讲解与linux内核相关的NIO实现,固然,windows或其余操做系统实现大致上是相似的,相信你们也能够举一反三。
那么,本文从这里将从简到难,一步一步为你们讲解选择器的点点滴滴吧。
选择器的宏观理解
“有这么一种检查员,她工做在养鸡场,天天的工做就是不停的查看特定的鸡舍,若是有鸡生蛋了,或者须要喂食,或者有鸡生病了,就把相应信息记录下来,这样一来,鸡舍负责人想知道鸡舍的状况,只须要到检查员那里查询便可,固然,鸡舍负责人得事先告知检查员去查询哪些鸡舍。“
以上这段话即为选择器所作工做的一个比喻,实际上选择器为通道服务,通道事先告诉选择器:“我对某些事件感兴趣,如可读、可写等“,选择器在接受了一个或多个通道的委托后,开始选择工做,它的选择工做就彻底交给操做系统,linux下即为poll或epoll。
选择器的建立
当调用Selector.open()时,选择器经过专门的工厂SelectorProvider来建立Selector的实现,SelectorProvider屏蔽了不一样操做系统及版本建立实现的差别性。具体实现代码以下:
java.nio.channels.Selector
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
由于SelectorProvider自己为一个抽象类,经过调用provider()提供对应的Provider实现,如PollSelectorProvider、EPollSelectorProvider
java.nio.channels.spi.SelectorProvider
public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return (SelectorProvider)AccessController
.doPrivileged(new PrivilegedAction() {
public Object run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
默认的Provider实现即为DefaultSelectorProvider,经过调用create(),获得具体的SelectorProvider
sun.nio.ch.DefaultSelectorProvider
public static SelectorProvider create() {
PrivilegedAction pa = new GetPropertyAction("os.name");
String osname = (String) AccessController.doPrivileged(pa);
if ("SunOS".equals(osname)) {
return new sun.nio.ch.DevPollSelectorProvider();
}
// use EPollSelectorProvider for Linux kernels >= 2.6
if ("Linux".equals(osname)) {
pa = new GetPropertyAction("os.version");
String osversion = (String) AccessController.doPrivileged(pa);
String[] vers = osversion.split("\\.", 0);
if (vers.length >= 2) {
try {
int major = Integer.parseInt(vers[0]);
int minor = Integer.parseInt(vers[1]);
if (major > 2 || (major == 2 && minor >= 6)) {
return new sun.nio.ch.EPollSelectorProvider();
}
} catch (NumberFormatException x) {
// format not recognized
}
}
}
return new sun.nio.ch.PollSelectorProvider();
}
这是linux操做系统下的DefaultSelectorProvider的实现,能够看到,若是内核版本>=2.6则,具体的SelectorProvider为EPollSelectorProvider,不然为默认的PollSelectorProvider
结合上文,能够猜想一下EPollSelectorProvider提供的Selector确定是与内核epoll有关的,PollSelectorProvider提供的
Selector确定是与poll有关的。的确如此:
sun.nio.ch.EPollSelectorProvider
public AbstractSelector openSelector() throws IOException {
return new EPollSelectorImpl(this);
}
sun.nio.ch.PollSelectorProvider
public AbstractSelector openSelector() throws IOException {
return new PollSelectorImpl(this);
}linux