1. 程式人生 > >傳統IO的阻塞和NIO的非阻塞說明和NIO的優勢

傳統IO的阻塞和NIO的非阻塞說明和NIO的優勢

資料的傳遞需要從使用者空間或者磁碟等硬體拷貝至核心緩衝區,在從核心緩衝區拷貝至閘道器後傳輸至網路,網路暢通情況下計算機一邊向緩衝區寫資料,一邊將緩衝區的資料讀取至閘道器。

資料的接收需要從閘道器拷貝至核心緩衝區後,再從核心空間拷貝至使用者空間或者磁碟等硬體,網路暢通情況下計算機一邊將資料從閘道器接受寫入核心緩衝區,一邊將資料從緩衝區拷貝至使用者空間或者直接持久化至磁碟等。

當網路不暢通時,緩衝區被寫滿或者讀完,會產生阻塞IO事件,假設叫“緩衝區滿”和“緩衝區空”事件。

傳統IO在核心緩衝區觸發寫滿或者讀完事件時,會阻塞相應的處理執行緒,“緩衝區滿”會傳遞執行緒,“緩衝區空”會阻塞接收執行緒,他們分別在資料流的兩端,一端將資料寫入流,一端從流接受資料。

當網路重新通暢後,緩衝區處於非空非滿狀態時,觸發IO事件,假設叫“緩衝區非滿”和“緩衝區非空”事件,傳統IO在感知到此事件時會喚醒相應的處理執行緒,“緩衝區非滿”喚醒寫入執行緒,“緩衝區非空”喚醒接受執行緒。

NIO對緩衝區IO事件的處理不是由CPU喚醒執行緒來實現,而是將IO時間的處理委託給Selector物件。

NIO的非阻塞實現形式在開頭的那篇部落格已經講得和好了,我這裡就不說了。

下面說下NIO相對於傳統IO的優勢:

  1. 傳統IO在處理資料傳輸請求時,針對每個傳輸請求生成一個執行緒,如果IO異常,那麼執行緒阻塞,在IO恢復後喚醒處理執行緒。在同時處理大量連線時,會例項化大量的執行緒物件。每個執行緒的例項化和回收都需要消耗資源,jvm需要為其分配TLAB,然後初始化TLAB,最後繫結執行緒,執行緒結束時又需要回收TLAB,這些都需要CPU資源。
  2. NIO使用selector來輪詢IO流,內部使用poll或者epoll,以事件驅動形式來相應IO事件的處理。同一時間只需例項化很少的執行緒物件,通過對執行緒的複用來提高CPU資源的使用效率。
  3. CPU輪流為每個執行緒分配時間片的形式,間接的實現單物理核處理多執行緒。當執行緒越多時,每個執行緒分配到的時間片越短,或者迴圈分配的週期越長,CPU很多時間都耗費在了執行緒的切換上。執行緒切換包含執行緒上個執行緒資料的同步(TLAB同步),同步變數同步至主存,下個執行緒資料的載入等等,他們都是很耗費CPU資源的。
  4. 在同時處理大量連線,但活躍連線不多時,NIO的事件響應模式相比於傳統IO有著極大的效能提升。
  5. NIO還提供了FileChannel,以zero-copy的形式傳輸資料,相較於傳統的IO,資料不需要拷貝至使用者空間,可直接由物理硬體(磁碟等)通過核心緩衝區後直接傳遞至閘道器,極大的提高了效能。
  6. NIO提供了MappedByteBuffer,其將檔案直接對映到記憶體(這裡的記憶體指的是虛擬記憶體,並不是實體記憶體),能極大的提高IO吞吐能力。