国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

少啰嗦!一分鐘帶你讀懂Java的NIO和經典IO的區(qū)別

Meils / 2111人閱讀

摘要:的選擇器允許單個線程監(jiān)視多個輸入通道。一旦執(zhí)行的線程已經超過讀取代碼中的某個數(shù)據(jù)片段,該線程就不會在數(shù)據(jù)中向后移動通常不會。

1、引言

很多初涉網(wǎng)絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發(fā)現(xiàn)一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO?

在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之間的差異、典型用例,以及這些差異如何影響我們的網(wǎng)絡編程或數(shù)據(jù)傳輸代碼的設計和實現(xiàn)的。

本文沒有復雜理論,也沒有像網(wǎng)上基它文章一樣千篇一律的復制粘貼,有的只是接地氣的通俗易懂,希望能給你帶來幫助。

(本文同步發(fā)布于:http://www.52im.net/thread-26...)

2、相關文章

《Java新一代網(wǎng)絡編程模型AIO原理及Linux系統(tǒng)AIO介紹》
《Java NIO基礎視頻教程、MINA視頻教程、Netty快速入門視頻》

3、Java NIO和IO的主要區(qū)別

下表總結了Java NIO和IO之間的主要區(qū)別。我將在表格后面的部分中詳細介紹每個區(qū)別。

3.1 Stream Oriented vs. Buffer Oriented
Java NIO和IO之間的第一個重要區(qū)別是IO是面向流的,其中NIO是面向緩沖區(qū)的。那么,這意味著什么?

面向流的Java IO意味著您可以從流中一次讀取一個或多個字節(jié)。你對讀取的字節(jié)做什么取決于你。它們不會緩存在任何地方。此外,您無法在流中的數(shù)據(jù)中前后移動。如果需要在從流中讀取的數(shù)據(jù)中前后移動,則需要先將其緩存在緩沖區(qū)中。

Java NIO的面向緩沖區(qū)的方法略有不同。數(shù)據(jù)被讀入緩沖區(qū),稍后處理該緩沖區(qū)。你可以根據(jù)需要在緩沖區(qū)中前后移動。這使你在處理過程中具有更大的靈活性。但是,你還需要檢查緩沖區(qū)是否包含完整處理所需的所有數(shù)據(jù)。并且,你需要確保在將更多數(shù)據(jù)讀入緩沖區(qū)時,不要覆蓋尚未處理的緩沖區(qū)中的數(shù)據(jù)。

3.2 Blocking vs. Non-blocking IO
Java IO的各種流都是blocking的。這意味著,當線程調用read()或write()時,該線程將被阻塞,直到有一些數(shù)據(jù)要讀取,或者數(shù)據(jù)被完全寫入,在此期間,該線程無法執(zhí)行任何其他操作。

Java NIO的非阻塞模式允許線程請求從通道讀取數(shù)據(jù),并且只獲取當前可用的內容,或者根本沒有數(shù)據(jù),如果當前沒有數(shù)據(jù)可用。線程可以繼續(xù)使用其他內容,而不是在數(shù)據(jù)可供讀取之前保持阻塞狀態(tài)。

非阻塞寫入也是如此,線程可以請求將某些數(shù)據(jù)寫入通道,但不要等待它完全寫入。然后線程可以繼續(xù)并在同一時間做其他事情。

線程在IO調用中沒有阻塞時花費空閑時間,通常在此期間在其他通道上執(zhí)行IO。也就是說,單個線程現(xiàn)在可以管理多個輸入和輸出通道。

4、Selectors

Java NIO的選擇器允許單個線程監(jiān)視多個輸入通道。你可以使用選擇器注冊多個通道,然后使用單個線程“選擇”具有可用于處理的輸入的通道,或者選擇準備寫入的通道。這種選擇器機制使單個線程可以輕松管理多個通道。

5、NIO和經典IO如何影響應用程序的設計?

選擇NIO或IO作為IO工具包可能會影響應用程序設計的以下方面:

1)API調用NIO或IO類;

2)處理數(shù)據(jù);

3)用于處理數(shù)據(jù)的線程數(shù)。

5.1 API調用
當然,使用NIO時的API調用看起來與使用IO時不同。這并不奇怪。而不是僅僅從例如InputStream讀取字節(jié)的數(shù)據(jù)字節(jié),必須首先將數(shù)據(jù)讀入緩沖區(qū),然后從那里進行處理。

5.2 數(shù)據(jù)處理
使用純NIO設計與IO設計時,數(shù)據(jù)處理也會受到影響。

在IO設計中,您從InputStream或Reader中讀取字節(jié)的數(shù)據(jù)字節(jié)。想象一下,您正在處理基于行的文本數(shù)據(jù)流。

例如:

Name: Anna

Age: 25

Email: [url=mailto:anna@mailserver.com]anna@mailserver.com[/url]

Phone: 1234567890

這個文本行流可以像這樣處理:

InputStream input = ... ; // get the InputStream from the client socket

BufferedReader reader = newBufferedReader(newInputStreamReader(input));


String nameLine   = reader.readLine();

String ageLine    = reader.readLine();

String emailLine  = reader.readLine();

String phoneLine  = reader.readLine();

注意處理狀態(tài)是如何,由程序執(zhí)行的程度決定的。換句話說,一旦第一個reader.readLine()方法返回,您就確定已經讀取了整行文本。readLine()會阻塞直到讀取整行,這就是原因。您還知道此行包含名稱。同樣,當?shù)诙€readLine()調用返回時,您知道此行包含年齡等。

正如您所看到的,只有當有新數(shù)據(jù)要讀取時,程序才會進行,并且對于每個步驟,您都知道該數(shù)據(jù)是什么。一旦執(zhí)行的線程已經超過讀取代碼中的某個數(shù)據(jù)片段,該線程就不會在數(shù)據(jù)中向后移動(通常不會)。

此圖中還說明了此原則:

▲ Java IO:從阻塞流中讀取數(shù)據(jù)

NIO的實現(xiàn)看起來會有所不同,這是一個簡化的例子:

ByteBuffer buffer = ByteBuffer.allocate(48);

intbytesRead = inChannel.read(buffer);

注意第二行從通道讀取字節(jié)到ByteBuffer。當該方法調用返回時,您不知道所需的所有數(shù)據(jù)是否都在緩沖區(qū)內。你只知道緩沖區(qū)包含一些字節(jié),這使得處理更加困難。

想象一下,在第一次讀取(緩沖)調用之后,是否所有讀入緩沖區(qū)的內容都是半行。例如,“姓名:An”。你能處理這些數(shù)據(jù)嗎?并不是的。在完成任何數(shù)據(jù)的處理之前,您需要等待至少一整行數(shù)據(jù)進入緩沖區(qū)。

那么你怎么知道緩沖區(qū)是否包含足夠的數(shù)據(jù)來處理它?好吧,你沒有。找出的唯一方法是查看緩沖區(qū)中的數(shù)據(jù)。結果是,在您知道所有數(shù)據(jù)是否存在之前,您可能需要多次檢查緩沖區(qū)中的數(shù)據(jù)。這既低效又可能在程序設計方面變得混亂。

例如:

ByteBuffer buffer = ByteBuffer.allocate(48);

intbytesRead = inChannel.read(buffer);

while(! bufferFull(bytesRead) ) {

bytesRead = inChannel.read(buffer);

}

bufferFull()方法必須跟蹤讀入緩沖區(qū)的數(shù)據(jù)量,并返回true或false,具體取決于緩沖區(qū)是否已滿。換句話說,如果緩沖區(qū)已準備好進行處理,則認為它已滿。

bufferFull()方法掃描緩沖區(qū),但必須使緩沖區(qū)保持與調用bufferFull()方法之前相同的狀態(tài)。如果不是,則可能無法在正確的位置讀入讀入緩沖區(qū)的下一個數(shù)據(jù)。這不是不可能的,但這是另一個需要注意的問題。

如果緩沖區(qū)已滿,則可以對其進行處理。如果它不滿,您可能能夠部分處理那里的任何數(shù)據(jù),如果這在您的特定情況下是有意義的。在許多情況下,它沒有。

這個圖中說明了is-data-in-buffer-ready循環(huán):

▲ Java NIO:從通道讀取數(shù)據(jù),直到所有需要的數(shù)據(jù)都在緩沖區(qū)中

6、什么時候該用NIO?什么時候該用經典IO?

NIO允許您僅使用一個(或幾個)線程來管理多個通道(網(wǎng)絡連接或文件),但成本是解析數(shù)據(jù)可能比從阻塞流中讀取數(shù)據(jù)時更復雜。

如果您需要同時管理數(shù)千個打開的連接,每個只發(fā)送一些數(shù)據(jù),例如聊天服務器,在NIO中實現(xiàn)服務器可能是一個優(yōu)勢。同樣,如果您需要與其他計算機保持大量開放連接,例如在P2P網(wǎng)絡中,使用單個線程來管理所有出站連接可能是一個優(yōu)勢。

此圖中說明了這一個線程,多個連接設計:

▲ Java NIO:管理多個連接的單個線程

如果您擁有較少帶寬的連接,一次發(fā)送大量數(shù)據(jù),那么可能最經典的IO服務器實現(xiàn)可能是最合適的。

此圖說明了經典的IO服務器設計:

▲ Java IO:經典的IO服務器設計 - 由一個線程處理的一個連接

7、更簡化的理解

以眾所周之的數(shù)據(jù)讀取過程為例,我們來一個更簡化的理解。

對于數(shù)據(jù)讀取,就讀取速度來說:CPU > 內存 > 硬盤。

I- 就是從硬盤到內存

O- 就是從內存到硬盤

第一種方式:從硬盤讀取數(shù)據(jù),然后程序一直等,數(shù)據(jù)讀完后,繼續(xù)你的操作。這種方式是最簡單的,叫阻塞IO(也就是經典IO)。

第二種方式:從硬盤讀取數(shù)據(jù),然后程序繼續(xù)向下執(zhí)行,等數(shù)據(jù)讀取完后,通知當前程序讀取完成(對硬件來說叫中斷,對程序來說叫回調),然后此程序可以立即處理讀取的數(shù)據(jù),也可以執(zhí)行完當前操作后再對讀取完的數(shù)據(jù)進行操作。

8、總而言之

還是以數(shù)據(jù)讀取為例,操作系統(tǒng)是按塊Block(塊)從硬盤拿數(shù)據(jù),就如同一個大臉盆,一下子就放入了一盆水。但是,當 Java 使用的時候,舊的 IO(經典IO)確實基于 流 Stream的,也就是雖然操作系統(tǒng)給我了一臉盆水,但是我得用吸管慢慢喝。

由于經典IO的重重落后理念,于是,NIO 橫空出世。。。

附錄:更多NIO異步網(wǎng)絡編程資料

《Java新一代網(wǎng)絡編程模型AIO原理及Linux系統(tǒng)AIO介紹》

《有關“為何選擇Netty”的11個疑問及解答》

《開源NIO框架八卦——到底是先有MINA還是先有Netty?》

《選Netty還是Mina:深入研究與對比(一)》

《選Netty還是Mina:深入研究與對比(二)》

《NIO框架入門(一):服務端基于Netty4的UDP雙向通信Demo演示》

《NIO框架入門(二):服務端基于MINA2的UDP雙向通信Demo演示》

《NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通信實戰(zhàn)》

《NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通信實戰(zhàn)》

《Netty 4.x學習(一):ByteBuf詳解》

《Netty 4.x學習(二):Channel和Pipeline詳解》

《Netty 4.x學習(三):線程模型詳解》

《Apache Mina框架高級篇(一):IoFilter詳解》

《Apache Mina框架高級篇(二):IoHandler詳解》

《MINA2 線程原理總結(含簡單測試實例)》

《Apache MINA2.0 開發(fā)指南(中文版)[附件下載]》

《MINA、Netty的源代碼(在線閱讀版)已整理發(fā)布》

《解決MINA數(shù)據(jù)傳輸中TCP的粘包、缺包問題(有源碼)》

《解決Mina中多個同類型Filter實例共存的問題》

《實踐總結:Netty3.x升級Netty4.x遇到的那些坑(線程篇)》

《實踐總結:Netty3.x VS Netty4.x的線程模型》

《詳解Netty的安全性:原理介紹、代碼演示(上篇)》

《詳解Netty的安全性:原理介紹、代碼演示(下篇)》

《詳解Netty的優(yōu)雅退出機制和原理》

《NIO框架詳解:Netty的高性能之道》

《Twitter:如何使用Netty 4來減少JVM的GC開銷(譯文)》

《絕對干貨:基于Netty實現(xiàn)海量接入的推送服務技術要點》

《Netty干貨分享:京東京麥的生產級TCP網(wǎng)關技術實踐總結》

《新手入門:目前為止最透徹的的Netty高性能原理和框架架構解析》

《寫給初學者:Java高性能NIO框架Netty的學習方法和進階策略》

《少啰嗦!一分鐘帶你讀懂Java的NIO和經典IO的區(qū)別》

更多同類文章 ……

(本文同步發(fā)布于:http://www.52im.net/thread-26...)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74991.html

相關文章

  • 阿里資深架構師之間,差不僅僅是年齡(進階必看)

    摘要:導讀閱讀本文需要有足夠的時間,筆者會由淺到深帶你一步一步了解一個資深架構師所要掌握的各類知識點,你也可以按照文章中所列的知識體系對比自身,對自己進行查漏補缺,覺得本文對你有幫助的話,可以點贊關注一下。目錄一基礎篇二進階篇三高級篇四架構篇五擴 導讀:閱讀本文需要有足夠的時間,筆者會由淺到深帶你一步一步了解一個資深架構師所要掌握的各類知識點,你也可以按照文章中所列的知識體系對比自身,對自己...

    huaixiaoz 評論0 收藏0
  • 從源碼入手,帶你讀懂Spring AOP面向切面編程

    摘要:,,面向切面編程。,切點,切面匹配連接點的點,一般與切點表達式相關,就是切面如何切點。例子中,注解就是切點表達式,匹配對應的連接點,通知,指在切面的某個特定的連接點上執(zhí)行的動作。,織入,將作用在的過程。因為源碼都是英文寫的。 之前《零基礎帶你看Spring源碼——IOC控制反轉》詳細講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動態(tài)代理嗎?看這篇就夠了》介紹了下...

    wawor4827 評論0 收藏0
  • 數(shù)據(jù)結構與算法(三):帶你讀懂選擇排序(Selection sort)

    摘要:基本介紹選擇式排序也屬于內部排序法,是從欲排序的數(shù)據(jù)中,按指定的規(guī)則選出某一元素,再依規(guī)定交換位置后達到排序的目的。而移動次數(shù)與序列的初始排序有關。空間復雜度簡單選擇排序需要占用個臨時空間,在交換數(shù)值時使用。 showImg(https://img-blog.csdnimg.cn/20190509221741422.gif); showImg(https://segmentfault....

    Kaede 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<