Java I/O工作機制及最佳化__Java

來源:互聯網
上載者:User
一、Java I/O 操作類分組
1.基於位元組操作的 I/O 介面:InputStream 和 OutputStream
2.基於字元操作的 I/O 介面:Writer 和 Reader
3.基於磁碟操作的 I/O 介面:File
4.基於網路操作的 I/O 介面:Socket
I/O 的核心問題要麼是資料格式影響 I/O 操作,要麼是傳輸方式影響 I/O 操作,也就是將什麼樣的資料寫到什麼地方的問題。

二、Java IO 工作機制 (1) 磁碟 I/O 工作機制
Java 中通常的 File 並不代表一個真實存在的檔案對象,當你通過指定一個路徑描述符時,它就會返回一個代表這個路徑相關聯的一個虛擬對象,這個可能是一個真實存在的檔案或者是一個包含多個檔案的目錄。何時真正會要檢查一個檔案存不存。就是在真正要讀取這個檔案時,如果檔案不存在,會拋出FileNotFoundException。

當傳入一個檔案路徑,將會根據這個路徑建立一個File 對象來標識這個檔案,然後將會根據這個File 對象建立真正讀取檔案的操作對象,這時將會真正建立一個關聯真實存在的磁碟檔案的檔案描述符 FileDescriptor,通過這個對象可以直接控制這個磁碟檔案。如果我們需要讀取的是字元格式設定,還需要StreamDecoder類將byte解碼為char(解碼過程) 至於如何從磁碟機上讀取一段資料,由作業系統幫我們完成。

(2)、Java Socket 的工作機制 主機 A 的應用程式要能和主機 B 的應用程式通訊,必須通過 Socket 建立串連,而建立 Socket 串連必須需要底層 TCP/IP 協議來建立 TCP 串連。建立 TCP 串連需要底層 IP 協議來定址網路中的主機。我們知道網路層使用的 IP 協議可以協助我們根據 IP 位址來找到目標主機,但是一台主機上可能運行著多個應用程式,如何才能與指定的應用程式通訊就要通過 TCP 或 UPD 的地址也就是連接埠號碼來指定。這樣就可以通過一個 Socket 執行個體唯一代表一個主機上的一個應用程式的通訊鏈路了。
a、建立通訊鏈路
當用戶端要與服務端通訊,用戶端首先要建立一個 Socket 執行個體,作業系統將為這個 Socket 執行個體分配一個沒有被使用的本地連接埠號碼,並建立一個包含本地和遠程地址和連接埠號碼的通訊端資料結構,這個資料結構將一直儲存在系統中直到這個串連關閉。在建立 Socket 執行個體的建構函式正確返回之前,將要進行 TCP 的三向交握協議,TCP 握手協議完成後,Socket 執行個體對象將建立完成,否則將拋出 IOException 錯誤。

與之對應的服務端將建立一個 ServerSocket 執行個體,ServerSocket 建立比較簡單只要指定的連接埠號碼沒有被佔用,一般執行個體建立都會成功,同時作業系統也會為 ServerSocket 執行個體建立一個底層資料結構,這個資料結構中包含指定監聽的連接埠號碼和包含監聽地址的萬用字元,通常情況下都是"*"即監聽所有地址。之後當調用 accept() 方法時,將進入阻塞狀態,等待用戶端的請求。當一個新的請求到來時,將為這個串連建立一個新的通訊端資料結構,該通訊端資料的資訊包含的地址和連接埠資訊正是請求源地址和連接埠。這個新建立的資料結構將會關聯到 ServerSocket 執行個體的一個未完成的串連資料結構列表中,注意這時服務端與之對應的 Socket 執行個體並沒有完成建立,而要等到與用戶端的三向交握完成後,這個服務端的 Socket 執行個體才會返回,並將這個 Socket 執行個體對應的資料結構從未自動完成清單中移到已自動完成清單中。所以 ServerSocket 所關聯的列表中每個資料結構,都代表與一個用戶端的建立的 TCP 串連。

b、資料轉送 傳輸資料是我們建立串連的主要目的,如何通過 Socket 傳輸資料。

當串連已經建立成功,服務端和用戶端都會擁有一個 Socket 執行個體,每個 Socket 執行個體都有一個 InputStream 和 OutputStream,正是通過這兩個對象來交換資料。同時我們也知道網路 I/O 都是以位元組流傳輸的。當 Socket 對象建立時,作業系統將會為 InputStream 和 OutputStream 分別分配一定大小的緩衝區,資料的寫入和讀取都是通過這個緩衝區完成的。寫入端將資料寫到 OutputStream 對應的 SendQ 隊列中,當隊列填滿時,資料將被發送到另一端 InputStream 的 RecvQ 隊列中,如果這時 RecvQ 已經滿了,那麼 OutputStream 的 write 方法將會阻塞直到 RecvQ 隊列有足夠的空間容納 SendQ 發送的資料。值得特別注意的是,這個緩衝區的大小以及寫入端的速度和讀取端的速度非常影響這個串連的資料轉送效率,由於可能會發生阻塞,所以網路 I/O 與磁碟 I/O 在資料的寫入和讀取還要有一個協調的過程,如果兩邊同時傳送資料時可能會產生死結。

三、Java I/O 調優

1、磁碟 I/O 最佳化

如我們可以壓力測試應用程式看系統的 I/O wait 指標是否正常,例如測試機器有 4 個 CPU,那麼理想的 I/O wait 參數不應該超過 25%,如果超過 25% 的話,I/O 很可能成為應用程式的效能瓶頸。Linux 作業系統下可以通過 iostat 命令查看。

2、網路 I/O 最佳化 網路 I/O 最佳化通常有一些基本處理原則:

1.一個是減少網路互動的次數:要減少網路互動的次數通常我們在需要網路互動的兩端會設定緩衝,比如 Oracle 的 JDBC 驅動程式,就提供了對查詢的 SQL 結果的緩衝,在用戶端和資料庫端都有,可以有效減少對資料庫的訪問。關於 Oracle JDBC 的記憶體管理可以參考《 Oracle JDBC 記憶體管理》。除了設定緩衝還有一個辦法是,合并訪問請求:如在查詢資料庫時,我們要查 10 個 id,我可以每次查一個 id,也可以一次查 10 個 id。再比如在訪問一個頁面時通過會有多個 js 或 css 的檔案,我們可以將多個 js 檔案合并在一個 HTTP 連結中,每個檔案用逗號隔開,然後發送到後端 Web 服務器根據這個 URL 連結,再拆分出各個檔案,然後打包再一併發回給前端瀏覽器。這些都是常用的減少網路 I/O 的辦法。

2.減少網路傳輸資料量的大小:減少網路資料量的辦法通常是將資料壓縮後再傳輸,如 HTTP 要求中,通常 Web 服務器將請求的 Web 頁面 gzip 壓縮後在傳輸給瀏覽器。還有就是通過設計簡單的協議,盡量通過讀取協議頭來擷取有用的價值資訊。盡量避免要讀取整個通訊資料來取得需要的資訊。

3.盡量減少編碼:通常在網路 I/O 中資料轉送都是以位元組形式的,也就是通常要序列化。但是我們發送要傳輸的資料都是字元形式的,從字元到位元組必須編碼。但是這個編碼過程是比較耗時的,所以在要經過網路 I/O 傳輸時,盡量直接以位元組形式發送。也就是盡量提前將字元轉化為位元組,或者減少字元到位元組的轉化過程。

4.根據應用情境設計合適的互動方式:所謂的互動情境主要包括同步與非同步阻塞與非阻塞方式。








聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.