作為一名程式員,io知識是必不可少,其實一直在和io打交道,要麼顯示要麼隱含給了操作系統,故做下關於io的記錄。說io之前呢,先介紹什麼叫同步非同步丶阻塞非阻塞 1. 同步非同步丶阻塞非阻塞 1.1 同步是指發出一個請求,在沒有得到結果之前該請求就不返回結果,請求返回時,也就得到結果了。比如我經常用燒水 ...
作為一名程式員,io知識是必不可少,其實一直在和io打交道,要麼顯示要麼隱含給了操作系統,故做下關於io的記錄。說io之前呢,先介紹什麼叫同步非同步丶阻塞非阻塞
1. 同步非同步丶阻塞非阻塞
1.1 同步是指發出一個請求,在沒有得到結果之前該請求就不返回結果,請求返回時,也就得到結果了。比如我經常用燒水壺燒水,沒燒開前一直盯著水壺(等水開)。
1.2 非同步是指發出一個請求後,立刻得到了回應,但沒有返回結果,這時我們可以再處理別的事情(發送其他請求),所以這種方式需要我們通過狀態主動查看是否有了結果, 或者可以設置一個回調來通知調用者。比如燒水時,不需要盯著水壺等水開,也可以做別的事:玩電腦,每兩三分鐘(類似輪詢任務)看看水開了沒有,也可以給水壺設置響鈴(信號通知,發郵件發簡訊),水開了通知了我(don’t call me,I call you)。
1.3 阻塞是指請求結果返回之前,當前線程會被掛起(被阻塞),線程什麼也做不了了,而非阻塞是指請求結果返回之前,當前線程沒有被阻塞,仍然可以做其他事情。
2. IO模型
一個io請求讀操作,數據會先被拷貝到操作系統內核的緩衝區中,然後從操作系統內核的緩衝區拷貝到應用程式的地址空間,所以整個過程可分為兩個階段:等待I/O數據準備好,這取決於IO目標返回數據的速度, 如網路IO時看網速和數據本身的大小;數據從內核緩衝區拷貝到進程內。
模型分類可分為以下幾種:BIO,NIO,IO多路復用,AIO,我就一一簡單介紹下
2.1 BIO
BIO,全稱是Blocking I/O,中文名叫:
阻塞 I/O,整個過程如圖:
應用程式發送請求給內核,然後由內核去進行通信,在內核准備好數據之前這個線程是被掛起的,所以在兩個階段程式都處於掛起狀態, 其 特點就是在IO執行的兩個階段都被block了 。
2.2 NIO
NIO,全稱是Non-Blocking IO,中文名字叫非阻塞IO,過程如圖示:
發起第一次請求後,線程並沒有被阻塞,它反覆檢查數據是否準備好,把原來大塊不能用的阻塞時間分成了許多“小阻塞”(檢查),所以進程不斷有機會被執行。這個檢查有沒有準備好數據的過程有點類似於“輪詢”。其特點就是程式需要不斷的主動詢問內核數據是否準備好。第一個階段非阻塞,第二個階段阻塞。
2.3 IO多路復用(重點,此模型不少中間件都用到了)
IO多路復用(I/O Multiplexing
)有select
,poll
,epoll
等不同方式,它的優點在於單個線程可以同時處理多個網路IO。不同於NIO
中輪詢操作是用戶線程進行的,而IO多路復用
調用操作系統級別的select
或poll或epoll
模型,由系統進行監控IO狀態。select輪詢可以監控許多socket的IO請求,當有一個socket的數據準備好時就可以返回。多路復用IO過程圖:
與NIO不同的是,select不是等到所有數據準備好才返回,而是只要有一個準備好就返回,它的強項在於可以同時處理多個連接。 其 特點是用戶進程能同時等待多個IO請求,系統來監控IO狀態,其中的任意一個進入讀就緒狀態,select函數就可以返回。 nio在java1.4才引入
2.4 AIO
AIO全稱是Asynchronous I/O,中文名叫:
非同步 I/O,它是Java1.7 才引入。整個過程中,用戶線程發起一個系統調用之後無須等待,可以處理別的事情。由操作系統等待接收內容,接收後把數據拷貝到用戶進程中,最後通知用戶程式已經可以使用數據了,兩個階段都是非阻塞的。整個過程如下圖
Java中可通過以下兩種方式實現:
一種是基於”回調”,我們可以實現CompletionHandler介面,在調用時把回調函數傳遞給對應的API即可;
一種是返回一個Future。處理完別的事情,可以通過isDone()可查看是否已經準備好數據,通過get()方法等待返回數據。
好了,暫且就寫這麼多,多多交流探討
參考:
1. OReilly.Java.I.O.2nd.Edition.May.2006
2. Unix網路編程捲1(幾種io模型)