【NIO】之IO和NIO的区别
在Java1.4之前的版本,Java對I/O的支持并不完善,開發(fā)人員在開發(fā)高性能I/O程序的時候,會面臨以下幾個問題:
1、沒有數(shù)據(jù)緩存區(qū),I/O性能存在問題
2、沒有C/C++通道的概念,輸入和輸出流是相互獨立的不能復(fù)用
3、同步阻塞式I/O通信(BIO),造成線程資源被長時間阻塞(致命缺陷)
4、硬件可移植性差,支持的字符集編碼有限
根據(jù)UNIX網(wǎng)絡(luò)編程的概念,I/O模型有五種
詳情請查看這篇文章
UNIX五種網(wǎng)絡(luò)I/O模型
在沒有JavaNIO之前呢,基于Java的所有的所有的Socket通信都采用了同步阻塞式模型(BIO)這種請求<->應(yīng)答的通信模式降低了開發(fā)難度,但是在性能和可靠性方面存在巨大缺陷,因此大型應(yīng)用服務(wù)器都是C/C++語言開發(fā),因為他們可以直接操作系統(tǒng)提供的異步的I/O或者是AIO能力。當(dāng)并發(fā)訪問量增大,響應(yīng)時間延遲增大之后,采用JavaBIO開發(fā)的服務(wù)器只能通過硬件擴(kuò)容來滿足高并發(fā)和低延時,極大增加了企業(yè)成本。
正是由于JavaBIO的不足,Java1.4版本之后提供了新的NIO庫,支持非阻塞式I/O操作。
JavaNIO提供了很多的異步I/O開發(fā)和API類庫,主要的類和接口如下:
進(jìn)行異步I/O操作的緩存區(qū)ByteBuffer
進(jìn)行異步I/O操作的管道Pipe
進(jìn)行各種I/O操作(異步或者同步)的Channel,包括ServerSocketChannel和SocketChannel
多種字符集編碼能力和解碼能力
實現(xiàn)非阻塞I/O操作的選擇器Selector
基于流行Perl實現(xiàn)的正則表達(dá)式庫
?
?了解NIO必須先了解幾個概念
| 什么是同步 |
| 什么是異步 |
| 什么是阻塞 |
| 什么是非阻塞 |
| 什么是同步阻塞 |
| 什么是同步非阻塞 |
| 什么是異步阻塞 |
| 什么是異步非阻塞 |
?
?
?
?
?
?
?
?
技術(shù)語言解釋:
?同步:當(dāng)一個進(jìn)程去訪問另一個進(jìn)程時,必須得到一個結(jié)果(指的是用戶進(jìn)程觸發(fā)IO操作并等待或者輪詢的去查看IO操作是否就緒)
異步:當(dāng)一個進(jìn)行訪問另一個進(jìn)程時時,不用立刻給結(jié)果,我會告訴你一個信息,你把結(jié)果放在這里,通知我即可(異步I/O就是Java將I/O讀寫操作委托給操作系統(tǒng),告訴操作系統(tǒng)將數(shù)據(jù)放到哪個緩存區(qū),數(shù)據(jù)大小)
阻塞:當(dāng)一個進(jìn)程去操作某個資源時發(fā)現(xiàn)這個資源不在或者暫時不可操作,那么這個進(jìn)程就一直等,等可以操作
非阻塞:當(dāng)進(jìn)程發(fā)現(xiàn)沒有資源可操作的時候立刻返回讀寫函數(shù),而不會等待
生活中的例子:
同步:比如電話好友,那么無論打通還是打不通,都會得到回應(yīng),(用戶接通了,用戶正在通話,用戶已關(guān)機(jī)等信息)
異步:比如叫餐,我們APP下單之后就可以做其他的事情,你只需要告訴地址,電話,食物到了送餐員會打電話通知你
阻塞:比如收費站堵車,這個就最能代表阻塞,你只能等著啥干不了
非阻塞:比如到銀行排隊辦理業(yè)務(wù),那么我們會拿一張排號小票,就可以去做其他事情,到號就會叫你!
網(wǎng)上有一個例子
同步阻塞:到飯店吃飯點餐,在那里等著不停的問,菜好了嗎?菜好了嗎?
同步非阻塞:點完餐,直接去打球,不過你需要隔一段時間來問一次,菜好了嗎?
異步阻塞:菜做好飯店打電話給你讓你親自去拿。
異步非阻塞:菜做好,飯店直接送到球場
所以我們歸納:
同步和異步是針對應(yīng)用程序和內(nèi)核的交互而言的,
1、同步指的是用戶進(jìn)程觸發(fā)I/O操作并等待或者輪詢的去查看I/O操作是否就緒,
2、異步是指用戶進(jìn)程觸發(fā)I/O操作以后便開始做自己的事情,而當(dāng)I/O操作已經(jīng)完成的時候會得到I/O完成的通知。
阻塞和非阻塞是針對于進(jìn)程在訪問數(shù)據(jù)的時候,根據(jù)I/O操作的就緒狀態(tài)來采取的不同方式,說白了是一種讀取或者寫入操作函數(shù)的實現(xiàn)方式,
1、阻塞方式下讀取或者寫入函數(shù)將一直等待
2、而非阻塞方式下,讀取或者寫入函數(shù)會立即返回一個狀態(tài)值。?
所以,I/O操作可以分為3類:同步阻塞(即早期的I/O操作)、同步非阻塞(NIO)、異步(AIO)。?
?
BIO
在JDK1.4之前,用Java編寫網(wǎng)絡(luò)請求,都是建立一個ServerSocket,然后,客戶端建立Socket時就會詢問是否有線程可以處理,如果沒有,要么等待,要么被拒絕。即:一個連接,要求Server對應(yīng)一個處理線程。
NIO
在Java里的由來,在JDK1.4及以后版本中提供了一套API來專門操作非阻塞I/O,我們可以在java.nio包及其子包中找到相關(guān)的類和接口。由于這套API是JDK新提供的I/O API,因此,也叫New I/O,這就是包名nio的由來。這套API由三個主要的部分組成:緩沖區(qū)(Buffers)、通道(Channels)和非阻塞I/O的核心類組成。在理解NIO的時候,需要區(qū)分,說的是New I/O還是非阻塞IO,New I/O是Java的包,NIO是非阻塞IO概念。這里講的是后面一種。
NIO本身是基于事件驅(qū)動思想來完成的,其主要想解決的是BIO的大并發(fā)問題: 在使用同步I/O的網(wǎng)絡(luò)應(yīng)用中,如果要同時處理多個客戶端請求,或是在客戶端要同時和多個服務(wù)器進(jìn)行通訊,就必須使用多線程來處理。也就是說,將每一個客戶端請求分配給一個線程來單獨處理。這樣做雖然可以達(dá)到我們的要求,但同時又會帶來另外一個問題。由于每創(chuàng)建一個線程,就要為這個線程分配一定的內(nèi)存空間(也叫工作存儲器),而且操作系統(tǒng)本身也對線程的總數(shù)有一定的限制。如果客戶端的請求過多,服務(wù)端程序可能會因為不堪重負(fù)而拒絕客戶端的請求,甚至服務(wù)器可能會因此而癱瘓。
NIO基于Reactor,當(dāng)socket有流可讀或可寫入socket時,操作系統(tǒng)會相應(yīng)的通知引用程序進(jìn)行處理,應(yīng)用再將流讀取到緩沖區(qū)或?qū)懭氩僮飨到y(tǒng)。
也就是說,這個時候,已經(jīng)不是一個連接就要對應(yīng)一個處理線程了,而是有效的請求,對應(yīng)一個線程,當(dāng)連接沒有數(shù)據(jù)時,是沒有工作線程來處理的。
AIO
與NIO不同,當(dāng)進(jìn)行讀寫操作時,只須直接調(diào)用API的read或write方法即可。這兩種方法均為異步的,對于讀操作而言,當(dāng)有流可讀取時,操作系統(tǒng)會將可讀的流傳入read方法的緩沖區(qū),并通知應(yīng)用程序;對于寫操作而言,當(dāng)操作系統(tǒng)將write方法傳遞的流寫入完畢時,操作系統(tǒng)主動通知應(yīng)用程序。
即可以理解為,read/write方法都是異步的,完成后會主動調(diào)用回調(diào)函數(shù)。
在JDK1.7中,這部分內(nèi)容被稱作NIO.2,主要在java.nio.channels包下增加了下面四個異步通道:
AsynchronousSocketChannel
AsynchronousServerSocketChannel
AsynchronousFileChannel
AsynchronousDatagramChannel
其中的read/write方法,會返回一個帶回調(diào)函數(shù)的對象,當(dāng)執(zhí)行完讀取/寫入操作后,直接調(diào)用回調(diào)函數(shù)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/gyjx2016/p/7219983.html
總結(jié)
以上是生活随笔為你收集整理的【NIO】之IO和NIO的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记录下log4j的两种配置方式
- 下一篇: HDU 2602.Bone Collec