隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2009年8月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          公告

          關注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網站

          關注的網站

          協議

          喜歡的Blog

          國內廣告平臺

          圖書出版

          在線培訓

          開發工具

          微博客戶端

          手機鈴聲

          操作系統

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統

          數學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1974565
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

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

          本文為原創,如需轉載,請注明作者和出處,謝謝!

          上一篇:Java網絡編程從入門到精通(30):定制accept方法

              在網絡應用中,一般可以采用同步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中的同步就是指除了以下兩種情況外程序會一直處于等待狀態:

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

          2. 在等待超時時間后,拋出了超時異常。

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

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

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

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

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

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

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

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

          下一篇:
          Java網絡編程從入門到精通(32):一個非阻塞I/O的例子





          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2009-08-16 10:46 銀河使者 閱讀(3135) 評論(2)  編輯  收藏 所屬分類: java 原創網絡編程

          評論

          # re: Java網絡編程從入門到精通(31):非阻塞I/O簡介  回復  更多評論   

          不錯uoa
          2009-08-16 11:03 | 99讀書人

          # re: Java網絡編程從入門到精通(31):非阻塞I/O簡介  回復  更多評論   

          第二部分第三段用的是同步I/O吧
          2015-04-22 15:21 | 老干爹
          主站蜘蛛池模板: 个旧市| 阜新| 江山市| 桐梓县| SHOW| 普定县| 宝山区| 石嘴山市| 三门县| 吉隆县| 临海市| 屯昌县| 平塘县| 澄城县| 巴楚县| 左贡县| 宜宾县| 罗田县| 益阳市| 潜山县| 依安县| 灌南县| 盘锦市| 顺义区| 湖州市| 综艺| 海原县| 和平县| 周宁县| 屏东县| 巨野县| 碌曲县| 甘洛县| 乡宁县| 桃源县| 陕西省| 油尖旺区| 克东县| 浦东新区| 旺苍县| 宣汉县|