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