摘要:是一個用來替代標準的新型數據傳遞方式,像現在分布式架構中會經常存在他的身影。這個方法會一直阻塞到某個注冊的通道有事件就緒。保持不變,仍然表示能從中讀取多少個元素等與通過調用方法,可以標記中的一個特定。
Java NIO是一個用來替代標準Java IO API的新型數據傳遞方式,像現在分布式架構中會經常存在他的身影。其比傳統的IO更加高效,非阻塞,異步,雙向
NIO主體結構Java NIO的主要構成核心就是Buffer、Channel和Selector這三個
對于Channel我想要提醒的是,Channel中的數據總是要先讀到一個Buffer,或者總是要從一個Buffer中寫入
使用Selector,得向Selector注冊Channel,然后調用它的select()方法。這個方法會一直阻塞到某個注冊的通道有事件就緒。一旦這個方法返回,線程就可以處理這些事件
Channel所有的 IO 在NIO 中都從一個Channel 開始。Channel 有點象流
Channel的實現FileChannel:從文件中讀寫數據
DatagramChannel:通過UDP讀寫網絡中的數據
SocketChannel:通過TCP讀寫網絡中的數據
ServerSocketChannel:監聽新進來的TCP連接,像Web服務器那樣。對每一個新進來的連接都會創建一個SocketChannel
Scatter/Gather分散(scatter)從Channel中讀取是指在讀操作時將讀取的數據寫入多個buffer中。因此,Channel將從Channel中讀取的數據“分散(scatter)”到多個Buffer中
聚集(gather)寫入Channel是指在寫操作時將多個buffer的數據寫入同一個Channel,因此,Channel 將多個Buffer中的數據“聚集(gather)”后發送到Channel
通過這樣的方式可以方便數據的讀取,當你想要獲取整個數據的一部分的時候,通過這種方式可以很快的獲取數據
ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); ByteBuffer[] bufferArray = { header, body }; channel.read(bufferArray);
read()方法按照buffer在數組中的順序將從channel中讀取的數據寫入到buffer,當一個buffer被寫滿后,channel緊接著向另一個buffer中寫
transferFrom、transferTo實現兩個Channel之間相互連接,數據傳遞
public static void trainforNio() { RandomAccessFile fromFile=null; RandomAccessFile toFile=null; try { fromFile = new RandomAccessFile("src/nio.txt", "rw"); // channel獲取數據 FileChannel fromChannel = fromFile.getChannel(); toFile = new RandomAccessFile("src/toFile.txt", "rw"); FileChannel toChannel = toFile.getChannel(); System.out.println(toChannel.size()); //position處開始向目標文件寫入數據,這里是toChannel long position = toChannel.size(); long count = fromChannel.size(); toChannel.transferFrom(fromChannel, position, count); System.out.println(toChannel.size()); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fromFile != null) { fromFile.close(); } if (toFile != null) { toFile.close(); } } catch (IOException e) { e.printStackTrace(); } } }
transferFrom、transferTo作用是一樣的,只是一個是tochannal調用,一個是fromchannnal調用
在實際的運用中可能存在源通道的剩余空間小于 count 個字節,則所傳輸的字節數要小于請求的字節數
在SoketChannel的實現中,SocketChannel只會傳輸此刻準備好的數據(可能不足count字節)。因此,SocketChannel可能不會將請求的所有數據(count個字節)全部傳輸到FileChannel中
看官一定要仔細看我栗子中的注釋
BufferBuffer是一個緩存區,其會將Channel中的數據存儲起來
Buffer的實現ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
MappedByteBuffer
capacity,position,limit在講解該主題之前,首先要明白讀模式和寫模式,無論是Channel還是Buffer都存在這兩種模式,要理解這兩種模式,第一步要明確主題是哪一個,是Channel還是Buffer。舉個栗子,主角是Channel,讀模式的含義就是從Buffer中獲取數據,寫模式就是將數據寫入Buffer,對于Buffer則是相反。搞清楚這一點,理解下面的就要相對清楚一點
capacity:作為一個內存塊,其就代表了當前Buffer能最多暫存多少數據量,存儲的數據類型則是根據上面的Buffer對象類型,一旦Buffer滿了,需要將其清空(通過讀數據或者清除數據)才能繼續寫數據往里寫數據
position:代表當前數據讀或寫處于那個位置。讀模式:被重置從0開始,最大值可能為capacity-1或者limit-1,寫模式:被重置從0開始,最大值為limit-1
limit:最多能往Buffer里寫多少數據,limit大小跟數據量大小和capacity有關,讀模式:數據量>capacity時,limit=capacity,數據量=capacity時,limit=capacity,數據量
import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Method { public static void nio() { RandomAccessFile aFile = null; try { aFile = new RandomAccessFile("src/nio.txt", "rw"); // channel獲取數據 FileChannel fileChannel = aFile.getChannel(); // 初始化Buffer,設定Buffer每次可以存儲數據量 // 創建的Buffer是1024byte的,如果實際數據本身就小于1024,那么limit就是實際數據大小 ByteBuffer buf = ByteBuffer.allocate(1024); // channel中的數據寫入Buffer int bytesRead = fileChannel.read(buf); System.out.println(bytesRead); while (bytesRead != -1) { // Buffer切換為讀取模式 buf.flip(); // 讀取數據 while (buf.hasRemaining()) { System.out.print((char) buf.get()); } // 清空Buffer區 buf.compact(); // 繼續將數據寫入緩存區 bytesRead = fileChannel.read(buf); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (aFile != null) { aFile.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { Method.nio();Buffer讀寫數據步驟
寫入數據到Buffer(fileChannel.read(buf))
調用flip()方法(buf.flip())
從Buffer中讀取數據(buf.get())
調用clear()方法或者compact()方法(buf.compact())
Buffer方法
flip():將Buffer讀模式切換到寫模式,并且將position制為0
clear():清空整個緩沖區
compact():只會清除已經讀過的數據。任何未讀的數據都被移到緩沖區的起始處,新寫入的數據將放到緩沖區未讀數據的后面
allocate(1024):初始化Buffer,設定的值就決定capacity值的大小
rewind():將position設回0,所以你可以重讀Buffer中的所有數據。limit保持不變,仍然表示能從Buffer中讀取多少個元素(byte、char等)
mark()與reset():通過調用Buffer.mark()方法,可以標記Buffer中的一個特定position。之后可以通過調用Buffer.reset()方法恢復到這個position
equals():當滿足下面三個條件時,兩個Buffer才是相等
有相同的類型(byte、char、int等)
Buffer中剩余的byte、char等的個數相等
Buffer中所有剩余的byte、char等都相同
只比較的是剩余的數據
compareTo():滿足下列條件,則認為一個Buffer“小于”另一個Buffer
第一個不相等的元素小于另一個Buffer中對應的元素
所有元素都相等,但第一個Buffer比另一個先耗盡(第一個Buffer的元素個數比另一個少)
SelectorSelector允許單線程處理多個 Channel。如果你的應用打開了多個連接(通道),但每個連接的流量都很低,使用Selector就會很方便
關于selector的知識內容比較多了,我打算在下一期進行詳細說明
更多內容可以關注微信公眾號,或者訪問AppZone網站
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64799.html
摘要:通道是和選擇器一起被注冊的,并且使用選擇器來更新通道的就緒狀態。注冊不會立即被取消,但鍵會立即失效。這個集合的每個成員都是相關的通道被選擇器在前一個選擇操作中判斷為已經準備好的,并且包 Java NIO是一個用來替代標準Java IO API的新型數據傳遞方式,像現在分布式架構中會經常存在他的身影。其比傳統的IO更加高效,非阻塞,異步,雙向 NIO主體結構 showImg(http:/...
摘要:而我們現在都已經發布了,的都不知道,這有點說不過去了。而對一個的讀寫也會有響應的描述符,稱為文件描述符,描述符就是一個數字,指向內核中的一個結構體文件路徑,數據區等一些屬性。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 本來我預想是先來回顧一下傳統的IO模式的,將傳統的IO模式的相關類理清楚(因為IO的類很多)。 但是,發現在整理的過程已...
摘要:前言本篇主要講解中的機制和網絡通訊中處理高并發的分為兩塊第一塊講解多線程下的機制第二塊講解如何在機制下優化資源的浪費服務器單線程下的機制就不用我介紹了,不懂得可以去查閱下資料那么多線程下,如果進行套接字的使用呢我們使用最簡單的服務器來幫助大 前言 本篇主要講解Java中的IO機制和網絡通訊中處理高并發的NIO 分為兩塊:第一塊講解多線程下的IO機制第二塊講解如何在IO機制下優化CPU資...
摘要:一緩沖區介紹用于和交互。的容量,位置,上限緩沖區實質上就是一塊內存,用于寫入數據,也供后續再次讀取數據。在每個類中,方法用于分配緩沖區。沒有這句話會報錯將此緩沖區的位置重置為先前標記的位置。返回此緩沖區的限制。 一 Buffer(緩沖區)介紹 Java NIO Buffers用于和NIO Channel交互。 我們從Channel中讀取數據到buffers里,從Buffer把數據寫入到...
摘要:當我們需要與進行交互時我們就需要使用到即數據從讀取到中并且從中寫入到中實際上一個其實就是一塊內存區域我們可以在這個內存區域中進行數據的讀寫其實是這樣的內存塊的一個封裝并提供了一些操作方法讓我們能夠方便地進行數據的讀寫類型有這些覆蓋了能從中傳 Java NIO Buffer 當我們需要與 NIO Channel 進行交互時, 我們就需要使用到 NIO Buffer, 即數據從 Buffe...
閱讀 1951·2021-09-07 09:59
閱讀 2520·2019-08-29 16:33
閱讀 3688·2019-08-29 16:18
閱讀 2849·2019-08-29 15:30
閱讀 1678·2019-08-29 13:52
閱讀 2035·2019-08-26 18:36
閱讀 530·2019-08-26 12:19
閱讀 694·2019-08-23 15:23