Java-NIO之Selector建立過程詳解

前言
java nio,一個入門netty以前須要瞭解下的非阻塞I/O實現,傳統的Socket通訊,啓動監聽後accept會一直處於阻塞狀態,那麼若是你想要多個(併發)通訊時,那麼咱們就須要多個線性去執行,並且還會存在一些無用線程佔用咱們的資源。java

nio的Selector很好的解決了這個問題,它能夠僅僅經過一個線程去跑多個鏈接,每一個鏈接沒有資格去佔用本身的線程,而是由Selector去分發。接下來讓咱們一塊兒來了解下做者的設計實現思路吧。設計模式

我也不是大神,你們有觀點也能夠提出來。安全

啓動Selector
使用過NIO的朋友都知道,要用就要先啓動Selector。併發

Selector selector = Selector.open();

沒錯,這樣一個非阻塞的功能就已經開始運行了,使用時間通知API以肯定在一組非阻塞套接字中,哪些已經就緒可以進行I/O相關的操做。ide

即一個單一線程處理多個併發的鏈接線程

源碼閱讀
首先咱們看看Selector這個類,它是一個抽象類,並無寫什麼具體實現,畢竟是Mark Reinhold寫的,怎麼可能那麼快就讓大家看到實在的東西呢?設計

public abstract class Selector implements Closeable{}

如今起碼咱們知道這個抽象類裏面起碼open這個靜態方法,Selector還實現了Closeable接口,Closeable是java.io的一個關閉接口,它自己也繼承了java.lang的AutoCloseable。netty

public interface Closeable extends AutoCloseable{    public void close() throws IOException;
}public interface AutoCloseable{    void close() throws Exception;
}

好了,目前還不難,咱們起碼知道Selector這個抽象類上面的部分關係,所以Selector固然也有本身的close方法,以下。code

public abstract class Selector implements Closeable {    //....

    public abstract void close() throws IOException;

}

open方法
接下來纔是重頭戲啦,open方法究竟作了啥,讓通訊鏈接在一個線程就能夠無缺的處理,它就行啓動了什麼大Boss。我有點喜歡這個做者了,他又一次讓我打開另外一扇門。繼承

public static Selector open() throws IOException {        return SelectorProvider.provider().openSelector();
}

又來一個SelectorProvider?

Selector的供應商?好吧,大佬們老是喜歡用一些設計模式的東西,沒錯,SelectorProvider也是一個抽象類,這個如今不用太在乎了。

SelectorProvider的構造方法,emmmm,你們看看就好

protected SelectorProvider() {
        SecurityManager sm = System.getSecurityManager();        if (sm != null)
            sm.checkPermission(new RuntimePermission("selectorProvider"));
}

SecurityManager(相似java安全的東西)、RuntimePermission(相似java權限的東西),大體就是很是安全的建立一個SelectorProvider。

回到原文,open方法調用了返回了一個Selector,是由SelectorProvider調用provider方法再調用openSelector而獲得的。

provider方法
咱們再看看provider方法吧,我都快急死了。一進來就看到synchronized!額,線程鎖,保證線程安全的東西,咱們理解主要的先,內容是這樣的。

public static SelectorProvider provider() {    synchronized (lock) {        if (provider != null)            return provider;        return AccessController.doPrivileged(        new PrivilegedAction<SelectorProvider>() {            public SelectorProvider run() {                if (loadProviderFromProperty())                    return provider;                if (loadProviderAsService())                    return provider;
                provider = sun.nio.ch.DefaultSelectorProvider.create();                return provider;
            }
        });
    }
}

哇,又來。首先就容量理解啦,provider不爲空就直接返回,這個provider是SelectorProvider自己的一個靜態成員

private static SelectorProvider provider = null;

固然第一次的時候必定是null的,而後就執行下面的方法,反正就是去判斷幾種狀況後返回一個provider。建立時用到了java反射機制哦,有興趣的朋友去看看。

那麼起碼咱們知道他也是判斷狀況後返回SelectorProvider。

openSelector方法
public abstract AbstractSelector openSelector()
        throws IOException;

淺顯易懂,返回一個新的selector

沒錯,一個簡單的open就是告訴你,你須要經過調用SelectorProvider的方法來生成系統默認SelectorProvider並返回一個okay的Selector。

結尾
emmmm,好像沒有真正的瞭解到如何經過一個線程來實現分發多個鏈接,不過沒關係,這麼牛逼的NIO怎麼可能一篇小文章就能說明白的?

下節繼續......

相關文章
相關標籤/搜索