日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java NIO (十四)NIO 和 IO 的区别和适用场景分析

發布時間:2023/12/19 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java NIO (十四)NIO 和 IO 的区别和适用场景分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在研究Java NIO和IO API時,很快就會想到一個問題:

什么時候應該使用IO,什么時候應該使用NIO?

在本文中,我將嘗試闡明Java NIO和IO之間的區別,它們的用例以及它們如何影響代碼的設計。 ###Java NIO和IO之間的主要區別 下表總結了Java NIO和IO之間的主要區別。 我將在表格后面的部分詳細介紹每個區別。

IONIO
面向流利用緩沖區
阻塞IO非阻塞IO
Selectors

###流導向vs緩沖導向 Java NIO和IO之間的第一大區別是IO是面向流的,其中NIO是面向緩沖區的。 那么,這是什么意思?

面向流的Java IO意味著您一次從流中讀取一個或多個字節。 你所做的讀字節取決于你。 他們沒有被緩存在任何地方。 而且,您不能前后移動數據流。 如果您需要前后移動從流中讀取的數據,則需要先將其緩存在緩沖區中。

Java NIO的面向緩沖區的方法略有不同。 數據被讀入一個緩沖區,稍后進行處理。 您可以根據需要前后移動緩沖區。 這給你在處理過程中更多的靈活性。 但是,您還需要檢查緩沖區是否包含您需要的所有數據,以便對其進行全面處理。 而且,您需要確保在將更多數據讀入緩沖區時,不會覆蓋尚未處理的緩沖區中的數據。 ###阻塞vs非阻塞IO Java IO的各種流都被阻塞。 這意味著,當一個線程調用一個read()或write()時,該線程被阻塞,直到有一些數據要讀取,或者數據被完全寫入。 線程在此期間不能做其他事情。

Java NIO的非阻塞模式使得線程可以請求從一個通道讀取數據,并且只獲取當前可用的數據,或者根本沒有任何數據可用。 線程可以繼續使用別的東西,而不是在數據可用于讀取之前保持阻塞狀態。

無阻塞寫入也是如此。 一個線程可以請求將一些數據寫入一個通道,但不要等待它被完全寫入。 線程然后可以繼續,同時做其他事情。

線程在沒有被IO阻塞的情況下花費空閑時間,通常是在其他通道上同時執行IO。 也就是說,一個線程現在可以管理多個輸入輸出通道。

###Selectors Java NIO的選擇器允許單線程監視多個輸入通道。 您可以使用選擇器注冊多個通道,然后使用單個線程“選擇”可用于處理的輸入通道,或者選擇準備寫入的通道。 這個選擇器機制使單個線程可以輕松管理多個通道。 ###NIO和IO如何影響應用程序設計 無論您選擇NIO還是IO作為您的IO工具包,都可能會影響您應用程序設計的以下方面:

  • API調用NIO或IO類。
  • 數據的處理。
  • 用于處理數據的線程數。 ###API調用 當然,使用NIO時的API調用看起來不同于使用IO時的調用。 這并不奇怪。 而不只是從例如數據字節讀取字節。 一個InputStream,數據必須首先被讀入一個緩沖區,然后從那里被處理。 ###數據處理 當使用純粹的NIO設計時,數據的處理也會受到IO設計的影響。
  • 在IO設計中,您從InputStream或Reader讀取字節的數據字節。 想象一下,你正在處理一系列基于行的文本數據。 例如:

    Name: Anna Age: 25 Email: anna@mailserver.com Phone: 1234567890 復制代碼

    這條文本行可以像這樣處理:

    InputStream input = ... ; // get the InputStream from the client socketBufferedReader 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()阻塞直到讀完整行,這就是為什么。 你也知道這行包含名字。 同樣,當第二個readLine()調用返回時,您知道該行包含年齡等

    正如你所看到的,只有當有新的數據要讀取時,程序才會進行,并且每一步你都知道數據是什么。 一旦正在執行的線程通過讀取代碼中的某段數據,線程就不會在數據中倒退(大部分不是)。 這個原理在這個圖中也有說明:

    NIO的實現看起來不同。 這是一個簡單的例子:

    ByteBuffer buffer = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buffer); 復制代碼

    注意從通道讀取字節到ByteBuffer的第二行。 當該方法調用返回時,您不知道所需的所有數據是否在緩沖區內。 所有你知道的是,緩沖區包含一些字節。 這使得處理有點困難。

    想象一下,如果在第一次讀取(緩沖區)調用之后,所有讀入緩沖區的內容都是半行。 例如,"Name: An"。 你能處理這些數據嗎? 不是真的。 你需要等待,直到完整的一行數據已經進入緩沖區,才有意義處理任何數據。

    那么如何知道緩沖區中是否包含足夠的數據才能處理? 那么,你沒有。 唯一的辦法就是查看緩沖區中的數據。 結果是,您可能需要多次檢查緩沖區中的數據,才能知道所有數據是否在內部。 這既是低效的,而且在程序設計方面可能變得混亂。 例如:

    ByteBuffer buffer = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buffer);while(! bufferFull(bytesRead) ) {bytesRead = inChannel.read(buffer); } 復制代碼

    bufferFull()方法必須跟蹤有多少數據被讀入緩沖區,并根據緩沖區是否已滿而返回true或false。 換句話說,如果緩沖區準備好處理,則認為已滿。

    bufferFull()方法掃描緩沖區,但必須保持緩沖區處于與調用bufferFull()方法之前相同的狀態。 否則,讀入緩沖區的下一個數據可能無法在正確的位置讀入。 這不是不可能的,但這是另一個需要注意的問題。

    如果緩沖區已滿,可以進行處理。 如果它沒有滿,那么你可能能夠部分處理任何數據,如果這在你的特定情況下是有意義的。 在許多情況下,它不是。

    圖中顯示了is-data-in-buffer-ready循環:

    ###概要 NIO允許您僅使用一個(或幾個)線程來管理多個通道(網絡連接或文件),但代價是解析數據可能比從阻塞流讀取數據時要復雜一些。

    如果你需要管理數以千計的同時打開的連接,每一個只發送一點點的數據,例如聊天服務器,在NIO中實現服務器可能是一個優勢。 同樣,如果你需要保持與其他計算機的大量開放連接,例如 在P2P網絡中,使用單個線程來管理所有出站連接可能是一個優勢。 這一個線程,多個連接設計如下圖所示:

    如果您的連接帶寬非常高,一次發送大量數據,那么傳統的IO服務器實現可能是最合適的。 該圖說明了一個經典的IO服務器設計:

    總結

    以上是生活随笔為你收集整理的Java NIO (十四)NIO 和 IO 的区别和适用场景分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。