1. 程式人生 > >漫話:如何給女朋友解釋什麼是BIO、NIO和AIO?

漫話:如何給女朋友解釋什麼是BIO、NIO和AIO?

週末午後,在家裡面進行電話面試,我問了面試者幾個關於IO的問題,其中包括什麼是BIO、NIO和AIO?三者有什麼區別?具體如何使用等問題,但是面試者回答的並不是很滿意。於是我在面試評價中寫道:"對Java的IO提醒理解不夠深入"。恰好被女朋友看到了。

Java IO

IO,常協作I/O,是Input/Output的簡稱,即輸入/輸出。通常指資料在內部儲存器(記憶體)和外部儲存器(硬碟、優盤等)或其他周邊裝置之間的輸入和輸出。

輸入/輸出是資訊處理系統(例如計算機)與外部世界(可能是人類或另一資訊處理系統)之間的通訊。

輸入是系統接收的訊號或資料,輸出則是從其傳送的訊號或資料。

在Java中,提供了一些列API,可以供開發者來讀寫外部資料或檔案。我們稱這些API為Java IO。

IO是Java中比較重要,且比較難的知識點,主要是因為隨著Java的發展,目前有三種IO共存。分別是BIO、NIO和AIO。

Java BIO

BIO 全稱Block-IO 是一種同步且阻塞的通訊模式。是一個比較傳統的通訊方式,模式簡單,使用方便。但併發處理能力低,通訊耗時,依賴網速。

Java NIO

Java NIO,全程 Non-Block IO ,是Java SE 1.4版以後,針對網路傳輸效能優化的新功能。是一種非阻塞同步的通訊模式。

NIO 與原來的 I/O 有同樣的作用和目的, 他們之間最重要的區別是資料打包和傳輸的方式。原來的 I/O 以流的方式處理資料,而 NIO 以塊的方式處理資料。

面向流的 I/O 系統一次一個位元組地處理資料。一個輸入流產生一個位元組的資料,一個輸出流消費一個位元組的資料。

面向塊的 I/O 系統以塊的形式處理資料。每一個操作都在一步中產生或者消費一個數據塊。按塊處理資料比按(流式的)位元組處理資料要快得多。但是面向塊的 I/O 缺少一些面向流的 I/O 所具有的優雅性和簡單性。

Java AIO

Java AIO,全程 Asynchronous IO,是非同步非阻塞的IO。是一種非阻塞非同步的通訊模式。

在NIO的基礎上引入了新的非同步通道的概念,並提供了非同步檔案通道和非同步套接字通道的實現。

三種IO的區別

首先,我們站在巨集觀的角度,重新畫一下重點:

BIO (Blocking I/O):同步阻塞I/O模式。

NIO (New I/O):同步非阻塞模式。

AIO (Asynchronous I/O):非同步非阻塞I/O模型。

那麼,同步阻塞、同步非阻塞、非同步非阻塞都是怎麼回事呢?關於這部分內容也可以檢視《漫話:如何給女朋友解釋什麼是IO中的阻塞、非阻塞、同步、非同步?》。

同步阻塞模式:這種模式下,我們的工作模式是先來到廚房,開始燒水,並坐在水壺面前一直等著水燒開。

同步非阻塞模式:這種模式下,我們的工作模式是先來到廚房,開始燒水,但是我們不一直坐在水壺前面等,而是回到客廳看電視,然後每隔幾分鐘到廚房看一下水有沒有燒開。

非同步非阻塞I/O模型:這種模式下,我們的工作模式是先來到廚房,開始燒水,我們不一一直坐在水壺前面等,也不隔一段時間去看一下,而是在客廳看電視,水壺上面有個開關,水燒開之後他會通知我。

阻塞VS非阻塞:人是否坐在水壺前面一直等。

同步VS非同步:水壺是不是在水燒開之後主動通知人。

適用場景

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

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

AIO方式適用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫OS參與併發操作,程式設計比較複雜,JDK7開始支援。

使用方式

使用BIO實現檔案的讀取和寫入。

//Initializes The ObjectUser1 user = new User1();user.setName("hollis");user.setAge(23);System.out.println(user);//Write Obj to FileObjectOutputStream oos = null;try {    oos = new ObjectOutputStream(new FileOutputStream("tempFile"));    oos.writeObject(user);} catch (IOException e) {    e.printStackTrace();} finally {    IOUtils.closeQuietly(oos);}//Read Obj from FileFile file = new File("tempFile");ObjectInputStream ois = null;try {    ois = new ObjectInputStream(new FileInputStream(file));    User1 newUser = (User1) ois.readObject();    System.out.println(newUser);} catch (IOException e) {    e.printStackTrace();} catch (ClassNotFoundException e) {    e.printStackTrace();} finally {    IOUtils.closeQuietly(ois);    try {        FileUtils.forceDelete(file);    } catch (IOException e) {        e.printStackTrace();    }}//Initializes The ObjectUser1 user = new User1();user.setName("hollis");user.setAge(23);System.out.println(user);//Write Obj to FileObjectOutputStream oos = null;try {    oos = new ObjectOutputStream(new FileOutputStream("tempFile"));    oos.writeObject(user);} catch (IOException e) {    e.printStackTrace();} finally {    IOUtils.closeQuietly(oos);}//Read Obj from FileFile file = new File("tempFile");ObjectInputStream ois = null;try {    ois = new ObjectInputStream(new FileInputStream(file));    User1 newUser = (User1) ois.readObject();    System.out.println(newUser);} catch (IOException e) {    e.printStackTrace();} catch (ClassNotFoundException e) {    e.printStackTrace();} finally {    IOUtils.closeQuietly(ois);    try {        FileUtils.forceDelete(file);    } catch (IOException e) {        e.printStackTrace();    }}

使用NIO實現檔案的讀取和寫入。

static void readNIO() {        String pathname = "C:\\Users\\adew\\Desktop\\jd-gui.cfg";        FileInputStream fin = null;        try {            fin = new FileInputStream(new File(pathname));            FileChannel channel = fin.getChannel();            int capacity = 100;// 位元組            ByteBuffer bf = ByteBuffer.allocate(capacity);            int length = -1;            while ((length = channel.read(bf)) != -1) {                bf.clear();                byte[] bytes = bf.array();                System.out.write(bytes, 0, length);                System.out.println();            }            channel.close();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            if (fin != null) {                try {                    fin.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    static void writeNIO() {        String filename = "out.txt";        FileOutputStream fos = null;        try {            fos = new FileOutputStream(new File(filename));            FileChannel channel = fos.getChannel();            ByteBuffer src = Charset.forName("utf8").encode("你好你好你好你好你好");            int length = 0;            while ((length = channel.write(src)) != 0) {                System.out.println("寫入長度:" + length);            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            if (fos != null) {                try {                    fos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }

使用AIO實現檔案的讀取和寫入

public class ReadFromFile {  public static void main(String[] args) throws Exception {    Path file = Paths.get("/usr/a.txt");    AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);    ByteBuffer buffer = ByteBuffer.allocate(100_000);    Future<Integer> result = channel.read(buffer, 0);    while (!result.isDone()) {      ProfitCalculator.calculateTax();    }    Integer bytesRead = result.get();    System.out.println("Bytes read [" + bytesRead + "]");  }}class ProfitCalculator {  public ProfitCalculator() {  }  public static void calculateTax() {  }}public class WriteToFile {  public static void main(String[] args) throws Exception {    AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(        Paths.get("/asynchronous.txt"), StandardOpenOption.READ,        StandardOpenOption.WRITE, StandardOpenOption.CREATE);    CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {      @Override      public void completed(Integer result, Object attachment) {        System.out.println("Attachment: " + attachment + " " + result            + " bytes written");        System.out.println("CompletionHandler Thread ID: "            + Thread.currentThread().getId());      }      @Override      public void failed(Throwable e, Object attachment) {        System.err.println("Attachment: " + attachment + " failed with:");        e.printStackTrace();      }    };    System.out.println("Main Thread ID: " + Thread.currentThread().getId());    fileChannel.write(ByteBuffer.wrap("Sample".getBytes()), 0, "First Write",        handler);    fileChannel.write(ByteBuffer.wrap("Box".getBytes()), 0, "Second Write",        handler);  }}

滴滴滴,水開了。

相關推薦

漫話如何女朋友解釋什麼是BIONIOAIO

​ 週末午後,在家裡面進行電話面試,我問了面試者幾個關於IO的問題,其中包括什麼是BIO、NIO和AIO?三者有什麼區別?具體如

漫話女朋友解釋為什麼隨機播放歌曲並不隨機

週末,開車帶女朋友出去玩,車裡面,隨機播放著周杰倫的歌曲。我正沉浸在『得兒飄,得兒飄,得兒意的飄』中,幻想著自己是秋名山車神,突然,旁邊的豆腐,哦不,女朋友說話了。

BIONIOAIO

IO的方式通常分為幾種,同步阻塞的BIO、同步非阻塞的NIO、非同步非阻塞的AIO。 一、BIO      在JDK1.4出來之前,我們建立網路連線的時候採用BIO模式,需要先在服務端啟動一個ServerSocket,然後在客戶端啟動Socket來對服務端進行通訊,預設情

BIONIOAIO的區別具體實現

一:理解同步:同步就是在發出一個*呼叫*時,在沒有得到結果之前,該*呼叫*就不返回,但是一旦呼叫返回,就得到返回值了。簡單的為:就是由*呼叫者*主動等待這個*呼叫*的結果。 二:非同步:*呼叫*在發出之後,這個呼叫就直接返回了,所以沒有返回結果;換句話說,當一個非同步過程呼

BIONIOAIO的區別(簡明版)

      一:事件分離器         在IO讀寫時,把 IO請求 與 讀寫操作 分離調配進行,需要用到事件分離器。根據處理機制的不同,事件分離器又分為:同步的Reactor和非同步的Proactor。         Reactor模型: - 應用程式

Java的BIONIOAIO介紹

1. I/O概念理解:同步/非同步、阻塞/非阻塞 一個IO操作其實分成了兩個步驟:發起IO請求和實際的IO操作。 同步IO和非同步IO的區別就在於第二個步驟是否阻塞,如果實際的IO讀寫阻塞請求程序,那麼就是同步IO。 阻塞IO和非阻塞IO的區別在於第一步,發

java高併發實戰(八)——BIONIOAIO

由於之前看的容易忘記,因此特記錄下來,以便學習總結與更好理解,該系列博文也是第一次記錄,所有有好多不完善之處請見諒與留言指出,如果有幸大家看到該博文,希望報以參考目的看瀏覽,如有錯誤之處,謝謝大家指出與留言。一、什麼是NIO?NIO是New I/O的簡稱,與舊式的基於流的I/

Java中BIONIOAIO的區別應用場景

最近一直在準備面試,為了使自己的Java水平更上一個檔次,拜讀了李林峰老師的《Netty權威指南》,瞭解了Java關於IO的發展和最新的技術,真是受益匪淺,現在把我總結的關於BIO、NIO和AIO的區別

BIONIOAIO的區別

  IO的方式通常分為幾種,同步阻塞的BIO、同步非阻塞的NIO、非同步非阻塞的AIO。 一、BIO 在JDK1.4出來之前,我們建立網路連線的時候採用BIO模式,需要先在服務端啟動一個ServerSocket,然後在客戶端啟動Socket來對服務端進行通訊,預設情況

漫話如何女朋友解釋什麼是併發並行

某天下班後,我在家裡進行電話面試,問到面試者這樣一個問題:"能不能簡單介紹一下你理解的併發和並行,並說明一下他們之間的關係"。但是面試者回答的並不好,所以我在面試評價中寫到:"對併發和並行的概念不清楚"。這時,女朋友看到這句話。 併發和並行最開始都是作業系統中的概念,表示的是CPU執

基礎 | BIONIOAIO

Java中的IO部分比較複雜,具體可參看書籍《Java NIO》和《Netty權威指南》。在此,僅對BIO、NIO和AIO進行概述性梳理,未涉及到具體實現細節,後續有空將深入展開。 同步IO和非同步IO 參考答案: IO操作主要分為兩個步驟,即發起IO請求和實際I

BIONIOAIO的區別

IO的方式通常分為幾種,同步阻塞的BIO、同步非阻塞的NIO、非同步非阻塞的AIO。    同步思想:就是當程式處理完一個請求或者操作的時候,再返回給使用者。使用者等待時間長,且不能關閉該程式或者這個頁面,必須等                   待該請求執行完,才能關閉或

BIONIOAIO講的很明白的文章

到底什麼是“IO Block” 很多人說BIO不好,會“block”,但到底什麼是IO的Block呢?考慮下面兩種情況: 用系統呼叫read從socket裡讀取一段資料 用系統呼叫read從一個磁碟檔案讀取一段資料到記憶體 如果你的直覺告訴你,這兩種都算“Block”,

結合程式碼詳細聊聊BIONIOAIO

作者:大寬寬 1、到底什麼是“IO Block” 很多人說BIO不好,會“block”,但到底什麼是IO的Block呢?考慮下面兩種情況: 用系統呼叫read從socket裡讀取一段資料 用系統呼叫read從一個磁碟檔案讀取一段資料到記憶體 如果你的直覺告

Java中BIONIOAIO使用樣例

上文中分析了阻塞,非阻塞,同步和非同步概念上的區別以及各種IO模型的操作流程,本篇文章將主要介紹Java中BIO,NIO和AIO三種IO模型如何使用。需要注意的是,本文中所提到的所有樣例都是在一個server對應一個client的情況下工作的,如果你想擴充套件為一個se

IONIOAIO的區別

IO和NIO的區別:其本質就是阻塞和非阻塞的區別。 阻塞概念:應用程式在獲取網路資料的時候,如果網路傳輸資料很慢,那麼久一直等著,知道傳輸完畢為止。 非阻塞概念:應用程式直接可以獲取已經準備就緒好的資料,無需等待。(從作業系統緩衝區中直接讀取已經緩衝完畢的資料,不用阻塞等待

漫話如何女朋友解釋為什麼雙11無法修改收貨地址

2018年11月11日上午11點,我拖著疲憊身軀回到家中,準備美美的睡上一覺,洗去身上值班一宿而帶來的疲憊。突然想到之前有交代女朋友讓她幫我搶東西,不知道怎麼樣了。 QPS、TR、併發使用者數、最佳執行緒數等等這些都是系統對併發處理上有關的概念。可以用來

漫話如何女朋友解釋為什麼雙11當天不能申請退款

雙十一當天晚上的十一點多,我下班回到家中,看到平時很早就睡覺的女朋友今天竟然還沒有睡覺。於是我問她: 服務降級:當伺服器壓力劇增的情況下,根據實際業務情況及流量,對一些服務和頁面有策略的不處理或換種簡單的方式處理,從而釋放伺服器資源以保證核心交易正常運作或高效運作。

漫話如何女朋友解釋什麼是DDoS攻擊?

週五下班比較早,我正在家裡面玩吃雞遊戲,正在瘋狂的跑毒,這時候坐在旁邊刷著抖音的女朋友問了我一個奇怪的問題。 分散式拒絕服務(DDoS:Distributed Denial of Service)攻擊,是指攻擊者利用大量“肉雞”對攻擊目標發動大量的正常或非正常請求、耗盡目標主機資

漫話如何女朋友解釋什麼是RPC

週末一大早,我正在電腦前面看新聞,突然女朋友大喊起來:哇,杭州下大雪啦,快來看啊。我並沒有理她,於是她跑過來拉我。 雪後杭州 RPC 是Remote Procedure Call的縮寫,譯為遠端過程呼叫。是一個計算機通訊協議。