摘要:一前言學習了和之后,肯定會問我們到底什么時候該使用,什么時候該使用在下文中我會嘗試用例子闡述和的區別,以及它們對你的設計會有什么影響。
一、前言
學習了Java IO 和 NIO之后,肯定會問:我們到底什么時候該使用 IO,什么時候該使用 NIO?
在下文中我會嘗試用例子闡述java NIO 和IO的區別,以及它們對你的設計會有什么影響。
IO | NIO |
---|---|
面向流(Stream) | 面向緩沖(Buffer) |
阻塞IO | 非阻塞IO |
無 | 選擇器(Selectors) |
Java NIO 和 IO 之間第一個最大的區別是,IO是面向流的,NIO是面向緩沖區的。
Java IO 面向流意味著每次從流中讀一個或多個字節,直至讀取所有字節,只能順序讀取所有數據。如果想要跳過一些字節或者想要讀取已經讀取過的數據,則必須將從流中的數據線緩存起來。
Java NIO的處理方式不一樣。數據一開始就被讀寫到緩沖區(Buffer),根據需要你可以控制讀取什么位置的數據。這就增加了處理過程中的靈活性。然而,你需要額外做的工作是檢查你需要的數據是否已經全部到了Buffer中,你還需要保證當有更多的數據進入Buffer中時,Buffer中未處理的數據不會被覆蓋
2.2 阻塞與非阻塞IOJava IO的各種流是阻塞的。這意味著,當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。
Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什么都不會獲取。而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閑時間用于在其它通道上執行IO操作,所以一個多帶帶的線程現在可以管理多個輸入和輸出通道(channel)。
2.3 SelectorsJava NIO 的 Selectors 允許一條線程去監控多個 channels 的輸入,你可以向一個 selector 上注冊多個channel,然后調用 selector 的 select() 方法判斷是否有新的連接進來或者已經在 selector 上注冊時channel 是否有數據進入。selector 的機制讓一個線程管理多個 channel變得簡單。
三、NIO和IO對應用的設計有何影響選擇使用NIO還是IO做你的IO工具對應用主要有以下幾個方面的影響
1、使用IO和NIO的API是不同的(廢話)
2、處理數據的方式
3、處理數據所用到的線程數
當然,使用NIO的API調用時看起來與使用IO時有所不同,但這并不意外,因為并不是僅從一個InputStream逐字節讀取,而是數據必須先讀入緩沖區再處理。
3.2 處理數據的方式在IO的設計里,要一個字節一個字節從InputStream 或者Reader中讀取數據,想象你正在處理一個向下面的基于行分割的流
Name:Anna Age: 25 Email: anna@mailserver.com Phone:1234567890
處理文本行的流的代碼應該向下面這樣
InputStream input = ... ; // get the InputStream from the client socket BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String nameLine = reader.readLine(); String ageLine = reader.readLine(); String emailLine = reader.readLine(); String phoneLine = reader.readLine();
注意,一旦reader.readLine()方法返回,你就可以確定整行已經被讀取,readLine()阻塞知道一整行都被讀取
NIO的實現會有一些不同,下面是一個簡單的例子
ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buffer);
注意第二行從channel中讀取數據到ByteBuffer,當這個方法返回你不知道是否你需要的所有數據都被讀到buffer了,你所知道的一切就是有一些數據被讀到了buffer中,但是你并不知道具體有多少數據,這使程序的處理變得稍微有些困難
想象一下,調用了read(buffer)方法后,只有半行數據被讀進了buffer,例如:“Name: An”,你能現在就處理數據嗎?當然不能。你需要等待直到至少一整行數據被讀到buffer中,在這之前確保程序不要處理buffer中的數據
你如何知道buffer中是否有足夠的數據可以被處理呢?你不知道,唯一的方法就是檢查buffer中的數據。可能你會進行幾次無效的檢查(檢查了幾次數據都不夠進行處理),這會令程序設計變得比較混亂復雜
ByteBuffer buffer = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buffer); while(! bufferFull(bytesRead) ) { bytesRead = inChannel.read(buffer); }
bufferFull()方法必須跟蹤有多少數據讀入緩沖區,并返回真或假,這取決于緩沖區是否已滿。換句話說,如果緩沖區準備好被處理,那么表示緩沖區滿了。
bufferFull()方法掃描緩沖區,但必須保持在bufferFull()方法被調用之前狀態相同。如果沒有,下一個讀入緩沖區的數據可能無法讀到正確的位置。這是不可能的,但卻是需要注意的又一問題。
如果緩沖區已滿,它可以被處理。如果它不滿,并且在你的實際案例中有意義,你或許能處理其中的部分數據。但是許多情況下并非如此。下圖展示了“緩沖區數據循環就緒”:
NIO可讓您只使用一個(或幾個)單線程管理多個通道(網絡連接或文件),但付出的代價是解析數據可能會比從一個阻塞流中讀取數據更復雜。
如果需要管理同時打開的成千上萬個連接,這些連接每次只是發送少量的數據,例如聊天服務器,實現NIO的服務器可能是一個優勢。同樣,如果你需要維持許多打開的連接到其他計算機上,如P2P網絡中,使用一個多帶帶的線程來管理你所有出站連接,可能是一個優勢。一個線程多個連接的設計方案如下圖所示:
如果你只有少量的連接但是每個連接都占有很高的帶寬,同時發送很多數據,傳統的IO會更適合。下圖說明了一個典型的IO服務器設計:
Java IO: 一個典型的IO服務器設計- 一個連接通過一個線程處理.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76346.html
摘要:的選擇器允許單個線程監視多個輸入通道。一旦執行的線程已經超過讀取代碼中的某個數據片段,該線程就不會在數據中向后移動通常不會。 1、引言 很多初涉網絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發現一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之...
摘要:而我們現在都已經發布了,的都不知道,這有點說不過去了。而對一個的讀寫也會有響應的描述符,稱為文件描述符,描述符就是一個數字,指向內核中的一個結構體文件路徑,數據區等一些屬性。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 本來我預想是先來回顧一下傳統的IO模式的,將傳統的IO模式的相關類理清楚(因為IO的類很多)。 但是,發現在整理的過程已...
摘要:的出現解決了這尷尬的問題,非阻塞模式下,通過,我們的線程只為已就緒的通道工作,不用盲目的重試了。注意要將注冊到,首先需要將設置為非阻塞模式,否則會拋異常。 showImg(https://segmentfault.com/img/remote/1460000017053374); 背景知識 同步、異步、阻塞、非阻塞 首先,這幾個概念非常容易搞混淆,但NIO中又有涉及,所以總結一下。 ...
摘要:的出現解決了這尷尬的問題,非阻塞模式下,通過,我們的線程只為已就緒的通道工作,不用盲目的重試了。注意要將注冊到,首先需要將設置為非阻塞模式,否則會拋異常。 同步、異步、阻塞、非阻塞首先,這幾個概念非常容易搞混淆,但NIO中又有涉及,所以總結一下[1]。 同步:API調用返回時調用者就知道操作的結果如何了(實際讀取/寫入了多少字節)。 異步:相對于同步,API調用返回時調用者不知道操作...
摘要:該線程在此期間不能再干任何事情了。線程通訊線程之間通過等方式通訊。選擇器傳統的模式會基于服務器會為每個客戶端請求建立一個線程由該線程單獨負貴處理一個客戶請求。 本文是對NIO知識的歸納與整理 1.阻塞與同步 1)阻塞(Block)和非租塞(NonBlock): 阻塞和非阻塞是進程在訪問數據的時候,數據是否準備就緒的一種處理方式,當數據沒有準備的時候阻塞:往往需要等待缞沖區中的數據準備好...
閱讀 1443·2021-11-22 13:54
閱讀 4323·2021-09-22 15:56
閱讀 1815·2021-09-03 10:30
閱讀 1318·2021-09-03 10:30
閱讀 2086·2019-08-30 15:55
閱讀 1851·2019-08-30 14:13
閱讀 2059·2019-08-29 15:19
閱讀 2341·2019-08-28 18:13