前言
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怎麼可能一篇小文章就能說明白的?
下節繼續......