首頁 > Java > java教程 > 主體

常見JAVA中IO/NIO模型

(*-*)浩
發布: 2019-08-23 15:39:37
轉載
2732 人瀏覽過

我們常見的IO模型有:阻塞 IO 模型、非阻塞 IO 模型、多路復用 IO 模型、 訊號驅動 IO 模型、異步 IO 模型;以下我們簡單介紹以上IO模型。

常見JAVA中IO/NIO模型

1、阻塞IO 模型

#最傳統的IO 模型,也就是讀寫資料過程中會發生阻塞現象。當用戶執行緒發出IO 請求之後,核心會去查看資料是否就緒,如果沒有就緒就會等待資料就緒,而用戶執行緒就會處於阻塞狀態,用戶執行緒交出CPU。當資料就緒之後,核心會將資料拷貝到使用者線程,並傳回結果給使用者線程,使用者線程才會解除block 狀態。典型的阻塞IO 模型的範例為:data = socket.read();如果資料沒有就緒,就會一直阻塞在read 方法。

2、非阻塞 IO 模型

當使用者執行緒啟動一個read 操作後,並不需要等待,而是馬上就得到了一個結果。如果結果是一個error 時,它就知道資料還沒準備好,於是它可以再次傳送read 操作。一旦核心中的資料準備好了,並且又再次收到了用戶線程的請求,那麼它馬上就將資料拷貝到了用戶線程,然後返回。所以事實上,在非阻塞IO 模型中,使用者執行緒需要不斷詢問核心資料是否就緒,也就說非阻塞IO不會交出CPU,而會一直佔用CPU。典型的非阻塞IO 模型一般如下:

while(true){
        data = socket.read();
        if(data!= error){
        处理数据
        break;
    }
}
登入後複製

但是對於非阻塞IO 就有一個非常嚴重的問題,在while 循環中需要不斷地去詢問內核資料是否就緒,這樣會導致CPU 佔用率非常高,因此一般情況下很少使用while 迴圈這種方式來讀取資料。

3、多路復用 IO 模型

多路復用IO 模型是目前使用得比較多的模型。

Java NIO 其實就是多路復用IO。在多路復用IO模型中,會有一個執行緒不斷去輪詢多個socket 的狀態,只有當socket 真正有讀寫事件時,才真正呼叫實際的IO 讀寫操作。

因為在多路復用IO 模型中,只需要使用一個線程就可以管理多個socket,系統不需要建立新的進程或線程,也不必維護這些線程和進程,並且只有在真正有socket 讀寫事件進行時,才會使用IO 資源,所以它大大減少了資源佔用。

在Java NIO 中,是透過selector.select()去查詢每個通道是否有到達事件,如果沒有事件,則一直阻塞在那裡,因此這種方式會導致使用者執行緒的阻塞。

多路復用IO 模式,透過一個執行緒就可以管理多個socket,只有當socket 真正有讀寫事件發生才會佔用資源來進行實際的讀寫操作。因此,多路復用IO 比較適合連接數比較多的情況。

另外多路復用IO 為何比非阻塞IO 模型的效率高是因為在非阻塞IO 中,不斷地詢問socket 狀態時透過使用者執行緒去進行的,而在多路復用IO 中,輪詢每個socket 狀態是核心在進行的,這個效率要比使用者執行緒要高的多。

不過要注意的是,多路復用IO 模型是透過輪詢的方式來偵測是否有事件到達,並且對到達的事件逐一回應。因此對於多路復用IO 模型來說,一旦事件回應體很大,那麼就會導致後續的事件遲遲無法處理,並且會影響新的事件輪詢。

4、訊號驅動IO 模型

在訊號驅動IO 模型中,當使用者執行緒發起一個IO 請求操作,會給對應的socket 註冊一個訊號函數,接著使用者執行緒會繼續執行,當核心資料就緒時會傳送一個訊號給使用者線程,使用者執行緒接收到訊號之後,便在訊號函數中呼叫IO 讀寫操作來進行實際的IO 請求操作。

5、非同步IO 模型

非同步IO 模型才是最理想的IO 模型,在非同步IO 模型中,當使用者執行緒發起read 操作之後,立刻就可以開始去做其它的事。

而另一方面,從核心的角度,當它受到一個asynchronous read 之後,它會立刻返回,說明read 請求已經成功發起了,因此不會對用戶線程產生任何block。

然後,核心會等待資料準備完成,然後將資料拷貝到使用者線程,當這一切都完成之後,核心會給使用者線程發送一個訊號,告訴它read 操作完成了。也就說使用者執行緒完全不需要實際的整個IO 操作是如何進行的,只需要先發起一個請求,當接收核心回傳的成功訊號時表示IO 操作已經完成,可以直接去使用資料了。

也就說在非同步IO 模型中,IO 操作的兩個階段都不會阻塞使用者線程,這兩個階段都是由核心自動完成,然後發送一個訊號告知使用者線程操作已完成。使用者執行緒中不需要再次呼叫IO 函數進行具體的讀寫。

這點是和訊號驅動模型有所不同的,在訊號驅動模型中,當使用者執行緒接收到訊號表示資料已經就緒,然後需要使用者執行緒呼叫IO 函數進行實際的讀寫操作;而在異步IO模型中,收到訊號表示IO 操作已經完成,不需要再在使用者執行緒中呼叫IO 函數進行實際的讀寫操作。

注意,非同步IO 是需要作業系統的底層支持,在Java 7 中,提供了Asynchronous IO。

以上是常見JAVA中IO/NIO模型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:csdn.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!