Java IO vs NIO vs AIO vs 協議Servlet 3.0 以及NIO的框架f

nio(new io) 
    同步 : 自己親自出馬持銀行卡到銀行取錢(使用同步IO時,Java自己處理IO讀寫)。 

    異步 : 委託一小弟拿銀行卡到銀行取錢,然後給你(使用異步IO時,Java將IO讀寫委託給OS處理,需要將數據緩衝區地址和大小傳給OS(銀行卡和密碼),OS需要支持異步IO操作API)。 

    阻塞 : ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回)。 

    非 阻塞 : 櫃檯取款,取個號,然後坐在椅子上做其它事,等號廣播會通知你辦理,沒到號你就不能去,你可以不斷問大堂經理排到了沒有,大堂經理如果說還沒到你就不能去 (使用非阻塞IO時,如果不能讀寫Java調用會馬上返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成)。 


一、IO  NIO  AIO 
io、nio、aio的區別,類似於resin、apache、nginx在io處理上的區別,從多線程互不干擾的阻塞式執行(resin),到輪詢式的同步非阻塞式(apache),再到異步非阻塞式(nginx)。 
現在這三種io都在jdk中予以了支持。 

1、IO  (BIO) 
同步並阻塞,服務器實現模式爲一個連接一個線程,每個線程親自處理io並且一直等待io的完成,即客戶端有連接請求時服務器端就需要啓動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。 
IO的侷限:IO是面向流的,阻塞式的,串行的一個過程。對每一個客戶端的socket連接,IO都需要一個線程來處理,而且在此期間,這個線程一直被佔用,直到socket關閉。在這期間,tcp的連接、數據的讀取、數據的返回都是被阻塞的。也就是說這期間大量的浪費了cpu的時間片和線程佔用的內存資源。 
每建立一個Socket連接時,同時創建一個新線程對該Socket進行單獨通信(採用阻塞的方式通信)。這種方式具有很高的響應速度,並且控制起來也很 簡單,在連接數較少的時候非常有效,但是如果對每一個連接都產生一個線程的無疑是對系統資源的一種浪費,如果連接數較多將會出現資源不足的情況。 

2、NIO (new IO) 從jdk1.4開始 
同步非阻塞,服務器實現模式爲一個請求一個線程,每個線程親自處理io,但有另外的線程輪詢檢查是否io準備完畢,不必等待io完成,即客戶端發送的連接請求都會註冊到多路複用器上,多路複用器輪詢到連接有I/O請求時才啓動一個線程進行處理。 
NIO則是面向緩衝區的,非阻塞式的,基於選擇器的,用一個線程來輪詢監控多個數據傳輸通道,哪個通道準備好了(即有了一組可以處理的數據),就處理哪個通道。 
服務器端保存一個Socket連接列表,然後對這個列表進行輪詢,如果發現某個Socket端口上有數據可讀時(讀就緒),則調用該socket連接的相 應讀操作;如果發現某個 Socket端口上有數據可寫時(寫就緒),則調用該socket連接的相應寫操作;如果某個端口的Socket連接已經中斷,則調用相應的析構方法關閉 該端口。這樣能充分利用服務器資源,效率得到了很大提高。 
3、AIO (Asynchronous io、NIO.2)  從jdk1.7開始 
http://stevex.blog.51cto.com/4300375/1284437 
異步非阻塞,服務器實現模式爲一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理,每個線程不必親自處理io,而是委派os來處理,並且也不需要等待io完成了,如果完成後,os會通知的。 
採用linux的epoll模型。 

3、結論 
在連接數不多的情況下,傳統IO編寫容易、方便使用。但是隨着連接數的增多,問題傳統IO就不行了。因爲傳統IO處理每個連接都要消耗一個線程,而程序的效率當線程數不多時是隨着線程數的增加而增加,但是到一定的數量之後,是隨着線程數的增加而減少。所以傳統阻塞式IO的 瓶頸在於不能處理過多的連接。 

非阻塞式IO的出現的目的就是爲了解決這個瓶頸。而非阻塞式IO是怎麼實現的呢?非阻塞IO處理連接的線程數和連接數沒有聯繫,也就是說處理10000個 連接非阻塞IO不需要10000個線程,你可以用1000個也可以用2000個線程來處理。因爲非阻塞IO處理連接是異步的。當某個連接發送請求到服務 器,服務器把這個連接請求當作一個請求"事件",並把這個"事件"分配給相應的函數處理。我們可以把這個處理函數放到線程中去執行,執行完就把線程歸還。 這樣一個線程就可以異步的處理多個事件。而阻塞式IO的線程的大部分時間都浪費在等待請求上了。 

然後NIO的非阻塞,需要一直輪詢,也是一個比較耗資源的。所以出現AIO 
4、BIO、NIO、AIO適用場景 

    BIO方式適用於連接數目比較小且固定的架構,這種方式對服務器資源要求比較高,併發侷限於應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。 

    NIO方式適用於連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4開始支持。 

    AIO方式使用於連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與併發操作,編程比較複雜,JDK7開始支持。 


ps:AIO、NIO是基於IO的,並不是取代IO的意思。 

二、NIO的框架 
IO的概念: 
1. 就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)。 
2. 然後呢 不同的操作系統對上述模型支持不同: unix支持io多路複用,不同系統叫法不同 :freebsd裏面叫 kqueue;linux 是epoll。而windows: 2000的時候就誕生了IOCP支持最後一種異步I/O 
3.java是一種跨平臺語言,爲了支持異步IO,誕生了nio,Java1.4引入的NIO 1.0是基於I/O複用的。在各個平臺上會選擇不同的複用方式。Linux用的epoll,BSD上用kqueue,Windows上應該是重疊I/O(肯定不是IOCP)。 
4:基於jdk的nio ,不同公司出了一堆框架:apache mina ,jboss的netty,sun的grizzly。 這些都是直接封裝傳輸層的tcp/udp。 

nio直接使用比較難用,所以有了netty等針對網絡io部分(tcp/udp-傳輸層)的封裝(nio也有非網絡io部分),爲了使nio更易用。 netty等只是一個nio框架,不需要web容器的額外支持,也就是說不限定web容器。 

3個NIO框架是: 
1、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等等。 

2、Netty 

Netty是一款異步的事件驅動的網絡應用框架和工具,用於快速開發可維護的高性能、高擴展性協議服務器和客戶端。也就是說,Netty是一個NIO客戶端/服務器框架,支持快速、簡單地開發網絡應用,如協議服務器和客戶端。它極大簡化了網絡編程,如TCP和UDP套接字服務器。 

3、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中提供的異步特性。 

可以說NIO的異步是直接處理的更底層的IO,而Servlet3.0的異步指的是上層的請求響應的異步 





參考: 
io vs nio: http://ifeve.com/java-nio-vs-io/ 
io vs nio vs aio: http://stevex.blog.51cto.com/4300375/1284437   
apache vs nginx: http://blog.csdn.net/xifeijian/article/details/17385831 
nio vs netty: http://www.iteye.com/problems/92400 
io vs nio: http://blog.csdn.net/showwair/article/details/7488518 
netty vs mina vs grizzly: http://blog.csdn.net/poechant/article/details/8439962 

io vs nio: http://blog.csdn.net/showwair/article/details/7488523

轉自:Java IO vs NIO vs AIO vs 協議Servlet 3.0 以及NIO的框架

Ps:附上在tomcat中修改BIO或者NIO connector的方法

打開tomcat-XXX\conf\server.xml文件,找到這句話<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

紅色部分表示當前使用的是BIO模式,把紅字修改爲"org.apache.coyote.http11.Http11NioProtocol"即啓動NIO模式.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章