1、NIO概述:php
http://www.cnblogs.com/dolphin0520/p/3919162.htmlhtml
http://weixiaolu.iteye.com/blog/1479656java
http://watchmen.cn/portal.php?mod=view&aid=509 好!網絡
2、文檔:多線程
http://tutorials.jenkov.com/java-nio/index.html併發
3、聊天室:函數
http://www.cnblogs.com/yanghuahui/p/3686054.htmlpost
4、nio原理:ui
一、Selector:spa
Selector的做用就是用來輪詢每一個註冊的Channel,一旦發現Channel有註冊的事件發生,便獲取事件而後進行處理。用單線程處理一個Selector,而後經過Selector.select()方法來獲取到達事件,在獲取了到達事件以後,就能夠逐個地對這些事件進行響應處理。
要使用Selector,得向Selector註冊Channel,而後調用它的select()方法(阻塞式方法)。這個方法會一直阻塞到某個註冊的通道有事件就緒。一旦這個方法返回,線程就能夠處理這些事件(如新鏈接進來,數據接收等)。
Selector可以檢測多個註冊的通道上是否有事件發生,若是有事件發生,便獲取事件而後針對每一個事件進行相應的響應處理。這樣一來,只是用一個單線程就能夠管理多個通道,也就是管理多個鏈接。這樣使得只有在鏈接真正有讀寫事件發生時,纔會調用函數來進行讀寫,就大大地減小了系統開銷,而且沒必要爲每一個鏈接都建立一個線程,不用去維護多個線程,而且避免了多線程之間的上下文切換致使的開銷。
與Selector有關的一個關鍵類是SelectionKey,一個SelectionKey表示一個到達的事件,這2個類構成了服務端處理業務的關鍵邏輯。
二、Channel:
Channel和傳統IO中的Stream很類似。雖然很類似,可是有很大的區別,主要區別爲:通道是雙向的,經過一個Channel既能夠進行讀,也能夠進行寫;而Stream只能進行單向操做,經過一個Stream只能進行讀或者寫
三、ByteBuffer:
上面的圖描述了從一個客戶端向服務端發送數據,而後服務端接收數據的過程。客戶端發送數據時,必須先將數據存入Buffer中,而後將Buffer中的內容寫入通道。服務端這邊接收數據必須經過Channel將數據讀入到Buffer中,而後再從Buffer中取出數據來處理。
神同樣的總結:
(1)、之前的流老是堵塞的,一個線程只要對它進行操做,其它操做就會被堵塞,也就至關於水管沒有閥門,你伸手接水的時候,無論水到了沒有,你就都只能耗在接水(流)上。
nio的Channel的加入,至關於增長了水龍頭(有閥門),雖然一個時刻也只能接一個水管的水,但依賴輪換策略,在水量不大的時候,各個水管裏流出來的水,均可以獲得妥善接納,這個關鍵之處就是增長了一個接水工,也就是Selector,他負責協調,也就是看哪根水管有水了的話,在當前水管的水接到必定程度的時候,就切換一下:臨時關上當前水龍頭,試着打開另外一個水龍頭(看看有沒有水)。
當其餘人須要用水的時候,不是直接去接水,而是事前提了一個水桶給接水工,這個水桶就是Buffer。也就是,其餘人雖然也可能要等,但不會在現場等,而是回家等,能夠作其它事去,水接滿了,接水工會通知他們。
這其實也是很是接近當前社會分工細化的現實,也是統分利用現有資源達到併發效果的一種很經濟的手段,而不是動不動就來個並行處理,雖然那樣是最簡單的,但也是最浪費資源的方式。
(2)、http://www.xuebuyuan.com/1600515.html
這就比如到餐廳吃飯,每來一桌客人,都有一個服務員專門爲你服務,從你到餐廳到結賬走人,這樣方式的好處是服務質量好,一對一的服務,VIP啊,但是缺點也很明顯,成本高,若是餐廳生意好,同時來100桌客人,就須要100個服務員,那老闆發工資的時候得心痛死了,這就是傳統的一個鏈接一個線程的方式。
老闆是什麼人啊,精着呢。這老闆就得捉摸怎麼能用10個服務員同時爲100桌客人服務呢,老闆就發現,服務員在爲客人服務的過程當中並非一直都忙着,客人點完菜,上完菜,吃着的這段時間,服務員就閒下來了,但是這個服務員仍是被這桌客人佔用着,不能爲別的客人服務,用華爲領導的話說,就是工做不飽滿。那怎麼把這段閒着的時間利用起來呢。這餐廳老闆就想了一個辦法,讓一個服務員(前臺)專門負責收集客人的需求,登記下來,好比有客人進來了、客人點菜了,客人要結賬了,都先記錄下來按順序排好。每一個服務員到這裏領一個需求,好比點菜,就拿着菜單幫客人點菜去了。點好菜之後,服務員立刻回來,領取下一個需求,繼續爲別人客人服務去了。這種方式服務質量就不如一對一的服務了,當客人數據不少的時候可能須要等待。但好處也很明顯,因爲在客人正吃飯着的時候服務員不用閒着了,服務員這個時間內能夠爲其餘客人服務了,原來10個服務員最多同時爲10桌客人服務,如今可能爲50桌,60客人服務了。
這種服務方式跟傳統的區別有兩個:
一、增長了一個角色,要有一個專門負責收集客人需求的人。NIO裏對應的就是Selector。
二、由阻塞服務方式改成非阻塞服務了,客人吃着的時候服務員不用一直侯在客人旁邊了。傳統的IO操做,好比read(),當沒有數據可讀的時候,線程一直阻塞被佔用,直到數據到來。NIO中沒有數據可讀時,read()會當即返回0,線程不會阻塞。
NIO中,客戶端建立一個鏈接後,先要將鏈接註冊到Selector,至關於客人進入餐廳後,告訴前臺你要用餐,前臺會告訴你你的桌號是幾號,而後你就可能到那張桌子坐下了,SelectionKey就是桌號。當某一桌須要服務時,前臺就記錄哪一桌須要什麼服務,好比1號桌要點菜,2號桌要結賬,服務員從前臺取一條記錄,根據記錄提供服務,完了再來取下一條。這樣服務的時間就被最有效的利用起來了。
(3)、http://zy116494718.iteye.com/blog/1387665
客戶端啓動了2個線程進行下載電影的工做,先啓動服務端,再運行客戶端,會看筆者本地的硬盤C分區到有以下效果。
能夠看到線程2的下載任務一直是0字節,等第一個線程下載完成後呢,線程2的下載任務才能進行。
服務端的代碼形成的問題就是使用傳統的sokect網絡通信,那麼另外一個客戶端的線程請求到server端的時候就發生了阻塞的狀況,也就是說,服務端至關一個廁所,廁所就有隻有一個坑位,來了一我的,至關於客戶端請求,那這我的至關於就把坑位給佔了,write操做和read操做會阻塞,這我的還沒解決完問題呢,下我的就來了,沒辦法,哥們兒先在門外等等啊,等前一個客戶爽完了再給您提供服務好吧。那麼如何解決這個佔着坑位不讓別人用的狀況呢?
寫模式下,往buffer裏寫一個字節,並把postion移動一位。寫模式下,通常limit與capacity相等。
寫完數據,須要開始讀的時候,將postion復位到0,並將limit設爲當前postion。
從buffer裏讀一個字節,並把postion移動一位。上限是limit,即寫入數據的最後位置。
mark相關的方法主要是mark()
(標記)和reset()
(回到標記),比較簡單,就不畫圖了。
6、byteBuffer讀寫文件
http://blog.csdn.net/gzu_imis/article/details/21109753
7、【Java.NIO】Selector,及SelectionKey 寫的不錯呀!
http://blog.csdn.net/robinjwong/article/category/2508639