記錄一下同步和異步,BIO,NIO,AIO

同步和異步:同步和異步是針對應用程序和內核的交互而言的
同步指的是用戶進程觸發IO 操作並等待或者輪詢的去查看IO 操作是否就緒。異步是指用戶進程觸發IO 操作以後便開始做自己的事情,而當IO 操作已經完成的時候會得到IO 完成的通知。

以銀行取款爲例:

同步 : 自己親自持銀行卡到銀行取錢(使用同步 IO 時,Java 自己處理IO 讀寫);

異步 : 委託員工拿銀行卡到銀行取錢,然後給你(使用異步IO 時,Java 將 IO 讀寫委託給OS 處理,需要將數據緩衝區地址和大小傳給OS(銀行卡和密碼),OS 需要支持異步IO操作API);

阻塞和非阻塞:阻塞和非阻塞是針對於進程在訪問數據的時候,在IO操作處於就緒狀態時採取的不同方式,就是一種讀取或者寫入操作方法的實現方式,阻塞方式下讀取或者寫入函數將一直等待,而非阻塞方式下,讀取或者寫入方法會立即返回一個狀態值。

以銀行取款爲例:

阻塞 : 在ATM機中排隊取款,只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回);

非阻塞 : 在櫃檯取款,先取號,然後就可以忙其他事,等廣播會通知你辦理,沒到號你就不能去,你可以不斷問經理排到了沒有,大堂經理如果說還沒到你就不能去(使用非阻塞IO時,如果不能讀寫Java調用會馬上返回,當IO事件分發器通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成)

1.BIO 編程

Blocking IO: 同步阻塞的編程方式。

BIO編程方式通常是在JDK1.4版本之前常用的編程方式。編程實現過程爲:首先在服務端啓動一個ServerSocket來監聽網絡請求,客戶端啓動Socket發起網絡請求,默認情況下ServerSocket回建立一個線程來處理此請求,如果服務端沒有線程可用,客戶端則會阻塞等待或遭到拒絕。

且建立好的連接,在通訊過程中,是同步的。在併發處理效率上比較低。大致結構如下:

同步並阻塞,服務器實現模式爲一個連接一個線程,即客戶端有連接請求時服務器端就需要啓動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。

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

使用線程池機制改善後的BIO模型圖如下:

2.NIO 編程:Unblocking IO(New IO): 同步非阻塞的編程方式。

NIO本身是基於事件驅動思想來完成的,其主要想解決的是BIO的大併發問題,NIO基於Reactor,當socket有流可讀或可寫入socket時,操作系統會相應的通知引用程序進行處理,應用再將流讀取到緩衝區或寫入操作系統。也就是說,這個時候,已經不是一個連接就要對應一個處理線程了,而是有效的請求,對應一個線程,當連接沒有數據時,是沒有工作線程來處理的。

NIO的最重要的地方是當一個連接創建後,不需要對應一個線程,這個連接會被註冊到多路複用器上面,所以所有的連接只需要一個線程就可以搞定,當這個線程中的多路複用器進行輪詢的時候,發現連接上有請求的話,纔開啓一個線程進行處理,也就是一個請求一個線程模式。

在NIO的處理方式中,當一個請求來的話,開啓線程進行處理,可能會等待後端應用的資源(JDBC連接等),其實這個線程就被阻塞了,當併發上來的話,還是會有BIO一樣的問題

3.AIO編程:Asynchronous IO: 異步非阻塞的編程方式。

與NIO不同,當進行讀寫操作時,只須直接調用API的read或write方法即可。這兩種方法均爲異步的,對於讀操作而言,當有流可讀取時,操作系統會將可讀的流傳入read方法的緩衝區,並通知應用程序;對於寫操作而言,當操作系統將write方法傳遞的流寫入完畢時,操作系統主動通知應用程序。即可以理解爲,read/write方法都是異步的,完成後會主動調用回調函數。在JDK1.7中,這部分內容被稱作NIO.2,主要在java.nio.channels包下增加了下面四個異步通道:AsynchronousSocketChannel、AsynchronousServerSocketChannel、AsynchronousFileChannel、AsynchronousDatagramChannel

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章