熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

Java網絡編程從入門到精通(31):非阻塞I/O簡介

2013-11-23 18:49:16  來源: Java核心技術 

  在網絡應用中一般可以采用同步I/O(阻塞I/O)和非阻塞I/O兩種方式進行數據通訊這兩種方式並非互相排斥和互相取代我們可以在平時的應用中單獨采用其中一種通訊方式也可以混合使用這兩種通訊方式在本文中就什麼是非阻塞I/O以及為什麼要使用這種通訊方式進行了介紹在下一篇文章中給出了一個簡單的例子來演示在網絡應用中如何使用非阻塞I/O進行通訊

  一什麼是非阻塞I/O

  我們可以將同步I/O稱為阻塞I/O非阻塞I/O稱為異步I/O在本書中采用了比較常用的叫法同步I/O和非阻塞I/O雖然它們的叫法不同但含義是一樣的讀者在閱讀其他書時應注意這一點

  在講解什麼是非阻塞I/O之前首先應了解什麼是同步I/O這裡的同步指的是什麼同步這個概念在程序設計中主要是指代碼按順序執行的過程如在Java程序中的main方法如果不使用多線程這個方法中的代碼一定是從前往後按順序執行的這就叫做同步如果使用了多線程從宏觀角度來看會有不同的代碼段同時執行這就叫做異步在同步I/O中的同步概念也類似也就是說在I/O通訊過程中只要是某一步的通訊未結束就無法進行其他的通訊那麼這裡的同步指的是什麼呢?要回答這個問題之前首先讓我們先回憶一下在網絡通訊中有哪些地方可能會被阻塞如果讀者看了前面的章節就會知道答案對於客戶端來說有兩個地方可能會被阻塞連接服務器(調用connect方法時)和讀寫數據而在服務端也有兩個地方可能會被阻塞等待客戶端請求(調用accept方法時)和讀寫數據(在一般情況下寫數據不會被阻塞但如果網絡環境比較差的時候客戶端和服務端的寫數據操作也可能發生阻塞現象)也就是說可以設置超時時間的地方就可能被阻塞而同步I/O中的同步就是指除了以下兩種情況外程序會一直處於等待狀態

   連接服務器讀寫數據或等待客戶端請求正常地執行

   在等待超時時間後拋出了超時異常

  在上面我們了解了什麼是同步I/O而非阻塞I/O和同步I/O最明顯的不同就是同步I/O所有可能被阻塞的地址在非阻塞I/O中都不會被阻塞如在讀取數據時如果數據暫時無法被讀取那麼在非阻塞I/O中會立刻返回以便程序可以執行其他的代碼然後系統會不斷偵測這個未完成的讀取操作直到可以繼續讀數據時再來完成這個操作

  Java在JDK及以後版本中提供了一套API來專門操作非阻塞I/O我們可以在javanio包及其子包中找到相關的類和接口由於這套API是JDK新提供的I/O API因此也叫New I/O這就是包名nio的由來這套API由三個主要的部分組成緩沖區(Buffers)通道(Channels)和非阻塞I/O的核心類組成這三部分的詳細內容將在本章的後面介紹

  二為什麼要使用非阻塞I/O

  在使用同步I/O的網絡應用中如果要同時處理多個客戶端請求或是在客戶端要同時和多個服務器進行通訊就必須使用多線程來處理也就是說將每一個客戶端請求分配給一個線程來單獨處理這樣做雖然可以達到我們的要求但同時又會帶來另外一個問題由於每創建一個線程就要為這個線程分配一定的內存空間(也叫工作存儲器)而且操作系統本身也對線程的總數有一定的限制如果客戶端的請求過多服務端程序可能會因為不堪重負而拒絕客戶端的請求甚至服務器可能會因此而癱瘓

  當然可以使用線程池(將在第三部分講解)來緩解服務器的壓力但這並不能解決客戶端因訪問過於密集而造成的服務器拒絕響應的問題雖然在服務端還有請求緩沖區作為保障但這個緩沖區的大小是有限的(一般為如果客戶端的請求數遠超過這個數客戶端還是會收到拒絕服務的信息

  在這種情況下使用非阻塞I/O就可以解決這個問題由於使用非阻塞I/O的程序一般是單線程的(有時可能將使用非阻塞I/O的程序段放到一個單獨的線程裡而主線程負責處理用戶的輸入)因此服務端接收的客戶端請求數並不隨著工作線程數的增加而增加所以使用非阻塞I/O模式就不會受到操作系統對線程總數的限制也不會占用大量的服務器資源

  非阻塞I/O雖然可以到達在處理大量客戶端請求的同時又不占用大量的服務器資源的目的但這種通訊方式並不能完全取代同步I/O如非阻塞I/O並不適合象FTP服務器那樣需要保持連接狀態的應用(原因將在以後的章節中說明)非阻塞I/O一般應用在服務端比較多一些因為客戶端一般並不需要處理大量的連接(但某些應用除外如象百度Google的Web Spider需要同時下載多個網頁這時就需要在客戶端建立大量的連接來滿足需求)而服務端程序一般需要接收並處理大量的客戶端請求因此就需要使用多線程(使用同步I/O)或非阻塞I/O來達到這個目的如果某個服務端應用處理的客戶端請求沒那麼多時使用多線程和同步I/O可能會更好一點因為這種方式要比非阻塞I/O方式更靈活

  在前面一直將非阻塞I/O和網絡應用放到一起講其實非阻塞I/O並不等於網絡我們也可以將非阻塞I/O應用到非網絡的應用中如文件復制由於同步I/O是基於字節流的而非阻塞I/O是基於緩沖區和通道的因此從理論上所操作的文件越大非阻塞I/O的優勢越能體現出來而對於比較小的文件操作這兩種方式的效率差不多根據實驗得知復制一個G左右的文件一般情況下非阻塞I/O方式比同步I/O方式快大約%左右


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25789.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.