摘要:前面說的輸入輸出流都是阻塞式的而且傳統的輸入輸出流都是通過字節的移動來處理即使不直接處理字節底層還是依賴字節處理也就是說面向輸輸出系統一次只能處理一個字節所以效率并不高新概述新使用不同的方式來處理輸入輸出采用內存映射文件的方式來處理輸入輸出
前面說的輸入輸出流都是阻塞式的.而且傳統的輸入輸出流都是通過字節的移動來處理(即使不直接處理字節,底層還是依賴字節處理),也就是說面向輸輸出系統一次只能處理一個字節,所以效率并不高.
新IO概述新IO使用不同的方式來處理輸入輸出.采用內存映射文件的方式來處理輸入輸出.它將文件的一段區域映射到內存中,像訪問內存一樣訪文件(模擬了操作系統上虛擬內存的概念). NIO中主要包包括:
java.nio 和Buffer相關的類
java.nio.channels 包括Channel和Selector相關類
java.nio.charset 和字符集相關的類
java.nio.charset.spi 提供字符集服務的相關類
Channel(通道)和Buffer(緩沖)是新IO中的兩個核心對象,Channel是對傳統輸入輸出系統的模擬.新IO系統中所有數據都要通過通道傳輸;Channel與傳統的InputStream,OutputStream最大區別在于提供了一個map方法,通過該map方法可以直接將"一塊數據"映射到內存中.如果說傳統的輸入輸出是面向流的處理,而新IO則是面向塊的處理.
Buffer可以被理解成一個容器,本質是一個數組,發送到Channel中所有對象都必須首先放到Buffer中,從而Channel的讀數據也必須先讀到Buffer中.Buffer允許一次次的取數據,也允許使用Channel直接將文件的某塊映射成Buffer.
Buffer結構上看,Buffer像一個數組,保存多個類型的相同數據.Buffer是一個抽象類.最常用子類是ByteBuffer,可在底層字節數組上做get/set操作.除ByteBuffer之外,對應其他基本數據類型(boolean除外)都有相對應的Buffer,ByteBuffer,CharBuffer,CharBuffer,ShortBuffer,IntBuffer等.這些類除了ByteBuffer之外,都采用類似或相同的方法來管理數據.只是各自管理的對象不同而已.這些Buffer都沒有提供構造器,通過如下方法得到一個Buffer對象:
static XxxBuffer allocate(int capacity) 創建一個容量為capacity的XxxBuffer對象
實際中使用較多的是ByteBuffer和CharBuffer.其他Buffer子類則較少使用.其中ByteBuffer的子類MappedByteBuffer,它用于表示Channel將磁盤文件的全部或部分映射到內存中得到的結果,通常MapByteBuffer對象由Channel的map對象返回.
Buffer中三個重要概念容量(capacity) 緩沖區容量,表示該Buffer的最大數據容量.即最多可以存儲多少數據.容量不能為負值,創建后也不可改變.
界限(limit) 第一個不應該被讀出或者寫入的緩沖區位置索引.limit后的位置既不可被讀取,也不可被寫.
位置(position) 用于指明下一個可以被讀出的或寫入緩沖區位置索引(類似IO流中的記錄指針).Buffer從Channel讀取數據時,position的位置等于恰好已經讀了多少數據,創建Buffer對象時,position為0,從Channel讀取了2個數據,position為2,指向Buffer中的第3的位置(第一個索引為0).
此外Buffer還支持一個可選標記mark,該mark允許直接將position指定位到mark處.這些值滿足如下關系:0 <= mark <= position <= limit <= capacity
Buffer的主要作用就是裝載數據,然后輸出數據.開始時Buffer的position為0,limit為capacity.程序不斷調用put向Buffer中放入數據(或從channel獲取數據),每放入一些數據,position向后移動一些位置.
當Buffer裝入數據結束后,調用filp方法,該方法將limit設置為position所在位置,將position設置為0.這樣使得從Buffer中讀取數據總是從0開始.讀完所有裝入的數據即結束.也就是說.Buffer調用filp后,Buffer為輸出數據做好了準備.
當Buffer輸出數據結束后,調用clear方法.將position置為0,將limit置為capacity,這樣為再次向Buffer中裝載數據做好準備.
Buffer中的常用方法: * int capacity() 返回Buffer的capacity大小 * boolean hasRemaining() 判斷當前位置(position)和界限(limit)之間是否還有元素可供處理. * int limit() 返回Buffer的界限(limit)的位置 * Buffer limit(int newLt) 重新設置界限(limit)的值,并返回一個具有新的limit的緩沖區對象. * Buffer mark() 設置Buffer的mark的位置,只能在0和position之間. * int position 返回當前Buffer中的當前位置. * Buffer position(int newPs) 設置Buffer的新位置,并返回一個具有改變position后的Buffer對象. * int remaining() 返回當前位置和界限(limit)之間的元素個數 * Buffer reset() 將位置(position)轉到mark所在的位置 * Buffer rewind() 將位置(position)設置為0,取消mark.
之外Buffer的所有子類還支持put/get方法.對Buffer進行數據的放入和取出.使用put/get來訪問Buffer中數據時,分為絕對和相對兩種: * 相對(Relative) 從Buffer當前位置讀取或寫入數據,然后將位置(position)的值按處理元素個數增加. * 絕對(Ansolut) 直接根據索引來向Buffer中讀取或寫入數據,使用絕對方式來訪問Buffer里的數據,并不會影響position的值.
//省略代碼 CharBuffer cbuf = CharBuffer.allocate(8); System.out.println("capacity:"+ cbuf.capacity()); System.out.println("limit" + cbuf.limit()); System.out.println("position:"+ cbuf.position()); cbuf.put("a"); cbuf.put("b"); cbuf.put("c"); System.out.println("加入三個元素后,position:" + cbuf.position()); cbuf.flip(); System.out.println("執行filp,limit:" + cbuf.limit()); System.out.println("position:" + cbuf.position()); //取出第一個元素 System.out.println("取出第一個元素:" + cbuf.get()); System.out.println("取出第一個元素后,position:" + cbuf.position()); cbuf.clear(); //limit置為capacity System.out.println("執行clear后,limit:" + cbuf.limit()); //capacity置0 System.out.println("執行clear后,position:" + cbuf.position()); //clear方法不清除緩沖區(buffer)中數據 System.out.println("執行clear后,緩沖區內容沒有被清除:" + cbuf.get(2)); //絕對讀取不影響position位置 System.out.println("執行絕對讀取后,position:" + cbuf.position()); //省略代碼Channel
//待更新
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64441.html
摘要:上篇說了最基礎的五種模型,相信大家對相關的概念應該有了一定的了解,這篇文章主要講講基于多路復用的。 上篇說了最基礎的五種IO模型,相信大家對IO相關的概念應該有了一定的了解,這篇文章主要講講基于多路復用IO的Java NIO。 背景 Java誕生至今,有好多種IO模型,從最早的Java IO到后來的Java NIO以及最新的Java AIO,每種IO模型都有它自己的特點,詳情請看我的上...
摘要:線程之間的切換對于操作系統來說是昂貴的。因此,單線程可以監視多個通道中的數據。當方法返回后,線程可以處理這些事件。 一 NIO簡介 Java NIO 是 java 1.4 之后新出的一套IO接口,這里的的新是相對于原有標準的Java IO和Java Networking接口。NIO提供了一種完全不同的操作方式。 NIO中的N可以理解為Non-blocking,不單純是New。 它支持面...
摘要:阻塞請求結果返回之前,當前線程被掛起。也就是說在異步中,不會對用戶線程產生任何阻塞。當前線程在拿到此次請求結果的過程中,可以做其它事情。事實上,可以只用一個線程處理所有的通道。 準備知識 同步、異步、阻塞、非阻塞 同步和異步說的是服務端消息的通知機制,阻塞和非阻塞說的是客戶端線程的狀態。已客戶端一次網絡請求為例做簡單說明: 同步同步是指一次請求沒有得到結果之前就不返回。 異步請求不會...
摘要:從通道進行數據寫入創建一個緩沖區,填充數據,并要求通道寫入數據。三之通道主要內容通道介紹通常來說中的所有都是從通道開始的。從中選擇選擇器維護注冊過的通道的集合,并且這種注冊關系都被封裝在當中停止選擇的方法方法和方法。 由于內容比較多,我下面放的一部分是我更新在我的微信公眾號上的鏈接,微信排版比較好看,更加利于閱讀。每一篇文章下面我都把文章的主要內容給列出來了,便于大家學習與回顧。 Ja...
摘要:的選擇器允許單個線程監視多個輸入通道。一旦執行的線程已經超過讀取代碼中的某個數據片段,該線程就不會在數據中向后移動通常不會。 1、引言 很多初涉網絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發現一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之...
閱讀 3940·2021-10-09 09:43
閱讀 2872·2021-10-08 10:05
閱讀 2734·2021-09-08 10:44
閱讀 883·2019-08-30 15:52
閱讀 2810·2019-08-26 17:01
閱讀 3017·2019-08-26 13:54
閱讀 1651·2019-08-26 10:48
閱讀 807·2019-08-23 14:41