Java NIO 選擇器(Selector)的內部實現(poll epoll)

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

相關文章
相關標籤/搜索