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