niojava
同步: 本身親自出馬持銀行卡到銀行取錢(使用同步IO時,Java本身處理IO讀寫)。linux
異步: 委託一小弟拿銀行卡到銀行取錢,而後給你(使用異步IO時,Java將IO讀寫委託給OS處理,須要將數據緩衝區地址和大小傳給OS(銀行卡和密碼),OS須要支持異步IO操做API)。nginx
阻塞: ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回)。web
非阻塞: 櫃檯取款,取個號,而後坐在椅子上作其它事,等號廣播會通知你辦理,沒到號你就不能去,你能夠不斷問大堂經理排到了沒有,大堂經理若是說還沒到你就不能去 (使用非阻塞IO時,若是不能讀寫Java調用會立刻返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成)。apache
1、IO NIO AIO編程
io、nio、aio的區別,相似於resin、apache、nginx在io處理上的區別,從多線程互不干擾的阻塞式執行(resin),到輪詢式的同步非阻塞式(apache),再到異步非阻塞式(nginx)。windows
如今這三種io都在jdk中予以了支持。tomcat
IO (BIO)服務器
同步並阻塞,服務器實現模式爲一個鏈接一個線程,每一個線程親自處理io而且一直等待io的完成,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,固然能夠經過線程池機制改善。網絡
IO的侷限:IO是面向流的,阻塞式的,串行的一個過程。對每個客戶端的socket鏈接,IO都須要一個線程來處理,並且在此期間,這個線程一直被佔用,直到socket關閉。在這期間,tcp的鏈接、數據的讀取、數據的返回都是被阻塞的。也就是說這期間大量的浪費了cpu的時間片和線程佔用的內存資源。
每創建一個Socket鏈接時,同時建立一個新線程對該Socket進行單獨通訊(採用阻塞的方式通訊)。這種方式具備很高的響應速度,而且控制起來也很簡單,在鏈接數較少的時候很是有效,可是若是對每個鏈接都產生一個線程的無疑是對系統資源的一種浪費,若是鏈接數較多將會出現資源不足的狀況。
NIO (new IO) 從jdk1.4開始
同步非阻塞,服務器實現模式爲一個請求一個線程,每一個線程親自處理io,但有另外的線程輪詢檢查是否io準備完畢,沒必要等待io完成,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。
**NIO則是面向緩衝區的,非阻塞式的,基於選擇器的,用一個線程來輪詢監控多個數據傳輸通道,哪一個通道準備好了(即有了一組能夠處理的數據),就處理哪一個通道。 **
服務器端保存一個Socket鏈接列表,而後對這個列表進行輪詢,若是發現某個Socket端口上有數據可讀時(讀就緒),則調用該socket鏈接的相應讀操做;若是發現某個 Socket端口上有數據可寫時(寫就緒),則調用該socket鏈接的相應寫操做;若是某個端口的Socket鏈接已經中斷,則調用相應的析構方法關閉 該端口。這樣能充分利用服務器資源,效率獲得了很大提升。
AIO (Asynchronous io、NIO.2) 從jdk1.7開始
異步非阻塞,服務器實現模式爲一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理,每一個線程沒必要親自處理io,而是委派os來處理,而且也不須要等待io完成了,若是完成後,os會通知的。
採用linux的epoll模型。
結論
在鏈接數很少的狀況下,傳統IO編寫容易、方便使用。可是隨着鏈接數的增多,問題傳統IO就不行了。由於傳統IO處理每一個鏈接都要消耗一個線程,而程序的效率當線程數很少時是隨着線程數的增長而增長,可是到必定的數量以後,是隨着線程數的增長而減小。因此傳統阻塞式IO的 瓶頸在於不能處理過多的鏈接。
非阻塞式IO的出現的目的就是爲了解決這個瓶頸。而非阻塞式IO是怎麼實現的呢?非阻塞IO處理鏈接的線程數和鏈接數沒有聯繫,也就是說處理10000個 鏈接非阻塞IO不須要10000個線程,你能夠用1000個也能夠用2000個線程來處理。由於非阻塞IO處理鏈接是異步的。當某個鏈接發送請求到服務 器,服務器把這個鏈接請求看成一個請求"事件",並把這個"事件"分配給相應的函數處理。咱們能夠把這個處理函數放到線程中去執行,執行完就把線程歸還。 這樣一個線程就能夠異步的處理多個事件。而阻塞式IO的線程的大部分時間都浪費在等待請求上了。
而後NIO的非阻塞,須要一直輪詢,也是一個比較耗資源的,因此出現AIO 。
BIO、NIO、AIO適用場景
** BIO方式適用於鏈接數目比較小且固定的架構,這種方式對服務器資源要求比較高,併發侷限於應用中,JDK1.4之前的惟一選擇,但程序直觀簡單易理解。**
**NIO方式適用於鏈接數目多且鏈接比較短(輕操做)的架構,好比聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4開始支持。 **
AIO方式使用於鏈接數目多且鏈接比較長(重操做)的架構,好比相冊服務器,充分調用OS參與併發操做,編程比較複雜,JDK7開始支持。
**ps:AIO、NIO是基於IO的,並非取代IO的意思。 **
2、NIO的框架
IO的概念:
就IO而言:概念上有5中模型:blocking I/O,nonblocking I/O,I/O multiplexing (select and poll),signal driven I/O (SIGIO),asynchronous I/O (the POSIX aio_functions)。
而後呢 不一樣的操做系統對上述模型支持不一樣: unix支持io多路複用,不一樣系統叫法不一樣 :freebsd裏面叫 kqueue;linux 是epoll。而windows: 2000的時候就誕生了IOCP支持最後一種異步I/O
java是一種跨平臺語言,爲了支持異步IO,誕生了nio,Java1.4引入的NIO 1.0是基於I/O複用的。在各個平臺上會選擇不一樣的複用方式。Linux用的epoll,BSD上用kqueue,Windows上應該是重疊I/O(確定不是IOCP)。
基於jdk的nio ,不一樣公司出了一堆框架:apache mina ,jboss的netty,sun的grizzly。 這些都是直接封裝傳輸層的tcp/udp。
nio直接使用比較難用,因此有了netty等針對網絡io部分(tcp/udp-傳輸層)的封裝(nio也有非網絡io部分),爲了使nio更易用。 ** netty等只是一個nio框架,不須要web容器的額外支持,也就是說不限定web容器。**
3個NIO框架是:
Mina
Mina(Multipurpose Infrastructure for Network Applications) 是 Apache組織一個較新的項目,它爲開發高性能和高可用性的網絡應用程序提供了很是便利的框架。當前發行的 Mina 版本2.04支持基於 JavaNIO 技術的 TCP/UDP 應用程序開發、串口通信程序,Mina 所支持的功能也在進一步的擴展中。目前,正在使用Mina的應用包括:Apache Directory Project、AsyncWeb、AMQP(Advanced MessageQueuing Protocol)、RED5 Server(Macromedia? FlashMedia RTMP)、ObjectRADIUS、 Openfire等等。
Netty
Netty是一款異步的事件驅動的網絡應用框架和工具,用於快速開發可維護的高性能、高擴展性協議服務器和客戶端。也就是說,Netty是一個NIO客戶端/服務器框架,支持快速、簡單地開發網絡應用,如協議服務器和客戶端。它極大簡化了網絡編程,如TCP和UDP套接字服務器。
Grizzly
Grizzly是一種應用程序框架,專門解決編寫成千上萬用戶訪問服務器時候產生的各類問題。使用JAVANIO做爲基礎,並隱藏其編程的複雜性。容易使用的高性能的API。帶來非阻塞socketd到協議處理層。利用高性能的緩衝和緩衝管理使用高性能的線程池。
Servlet3.0 vs NIO
servlet3.0是一個規範、或者協議,能夠用IO實現,也能夠用NIO實現,而NIO則只是一種技術實現。一個是架構,一個是具體技術。
相同:
都提供了異步功能。
不一樣:
jdk的nio直接使用比較難用,因此有了netty這些針對網絡io部分(tcp/udp-傳輸層)的封裝(nio也有非網絡io部分),爲了使nio更易用而已。
servlet3.0是另一個東西,不是對io的封裝,而是javaee6衆多規範中的一個。但凡javaee6的實現(或者像tomcat這種web容 器部分的實現),都會支持servlet3.0,servlet理論上能夠支持多種應用層協議(不僅僅只是http),而servlet3.0之後提供的 異步特性與javase提供的nio或aio無直接關係,就是使用bio同樣能夠實現servlet3.0中提供的異步特性。
總結
到這裏,深刻理解分佈式系統協調技術介紹就結束了,,不足之處還望你們多多包涵!!以爲收穫的話能夠點個關注收藏轉發一波喔,謝謝大佬們支持。(吹一波,233~~)