1. 程式人生 > >BIO、NIO和AIO的區別、具體實現

BIO、NIO和AIO的區別、具體實現

一:理解同步:同步就是在發出一個*呼叫*時,在沒有得到結果之前,該*呼叫*就不返回,但是一旦呼叫返回,就得到返回值了。簡單的為:就是由*呼叫者*主動等待這個*呼叫*的結果。

二:非同步:*呼叫*在發出之後,這個呼叫就直接返回了,所以沒有返回結果;換句話說,當一個非同步過程呼叫發出後,呼叫者不會立刻得到結果。而是在*呼叫*發出後,*被呼叫者*通過狀態、通知來通知呼叫者,或通過回撥函式處理這個呼叫。

生活案例

你打電話問書店老闆有沒有《分散式系統》這本書,如果是同步通訊機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。 而非同步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裡老闆通過“回電”這種方式來回調。

三:阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態.

四:阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起。呼叫執行緒只有在得到結果之後才會返回。 非阻塞呼叫指在不能立刻得到結果之前,該呼叫不會阻塞當前執行緒。 還是上面的例子, 你打電話問書店老闆有沒有《分散式系統》這本書,你如果是阻塞式呼叫,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式呼叫,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。 在這裡阻塞與非阻塞與是否同步非同步無關。跟老闆通過什麼方式回答你結果無關。

同步阻塞IO(BIO)

        我們熟知的Socket程式設計就是BIO,一個socket連線一個處理執行緒(這個執行緒負責這個Socket連線的一系列資料傳輸操作)。阻塞的原因在於:作業系統允許的執行緒數量是有限的,多個socket申請與服務端建立連線時,服務端不能提供相應數量的處理執行緒,沒有分配到處理執行緒的連線就會阻塞等待或被拒絕。

同步非阻塞IO(NIO)

         New IO是對BIO的改進,基於Reactor模型。我們知道,一個socket連線只有在特點時候才會發生資料傳輸IO操作,大部分時間這個“資料通道”是空閒的,但還是佔用著執行緒。NIO作出的改進就是“一個請求一個執行緒”,在連線到服務端的眾多socket中,只有需要進行IO操作的才能獲取服務端的處理執行緒進行IO。這樣就不會因為執行緒不夠用而限制了socket的接入。客戶端的socket連線到服務端時,就會在事件分離器註冊一個 IO請求事件 和 IO 事件處理器。在該連線發生IO請求時,IO事件處理器就會啟動一個執行緒來處理這個IO請求,不斷嘗試獲取系統的IO的使用許可權,一旦成功(即:可以進行IO),則通知這個socket進行IO資料傳輸。

         NIO還提供了兩個新概念:Buffer和Channel

Buffer:
–        是一塊連續的記憶體塊。
–        是 NIO 資料讀或寫的中轉地。
Channel:
–        資料的源頭或者資料的目的地
–        用於向 buffer 提供資料或者讀取 buffer 資料 ,buffer 物件的唯一介面。
–         非同步 I/O 支援
      Buffer作為IO流中資料的緩衝區,而Channel則作為socket的IO流與Buffer的傳輸通道。客戶端socket與服務端socket之間的IO傳輸不直接把資料交給CPU使用,
而是先經過Channel通道把資料儲存到Buffer,然後CPU直接從Buffer區讀寫資料,一次可以讀寫更多的內容。
      使用Buffer提高IO效率的原因(這裡與IO流裡面的BufferedXXStream、BufferedReader、BufferedWriter提高效能的原理一樣):IO的耗時主要花在資料傳輸的路上,普通的IO是一個位元組一個位元組地傳輸,
而採用了Buffer的話,通過Buffer封裝的方法(比如一次讀一行,則以行為單位傳輸而不是一個位元組一次進行傳輸)就可以實現“一大塊位元組”的傳輸。比如:IO就是送快遞,普通IO是一個快遞跑一趟,採用了Buffer的IO就是一車跑一趟。很明顯,buffer效率更高,花在傳輸路上
的時間大大縮短。

非同步阻塞IO(AIO)

          NIO是同步的IO,是因為程式需要IO操作時,必須獲得了IO許可權後親自進行IO操作才能進行下一步操作。AIO是對NIO的改進(所以AIO又叫NIO.2),它是基於Proactor模型的。每個socket連線在事件分離器註冊 IO完成事件 和 IO完成事件處理器。程式需要進行IO時,向分離器發出IO請求並把所用的Buffer區域告知分離器,分離器通知作業系統進行IO操作,作業系統自己不斷嘗試獲取IO許可權並進行IO操作(資料儲存在Buffer區),操作完成後通知分離器;分離器檢測到 IO完成事件,則啟用 IO完成事件處理器,處理器會通知程式說“IO已完成”,程式知道後就直接從Buffer區進行資料的讀寫。

          也就是說:AIO是發出IO請求後,由作業系統自己去獲取IO許可權並進行IO操作;NIO則是發出IO請求後,由執行緒不斷嘗試獲取IO許可權,獲取到後通知應用程式自己進行IO操作。

程式碼實現參考下面這篇博文: