Buffer
BIO的局限性
Server端應該使用盡肯能少的線程來處理多個client請求。BIO下,每個client都要創(chuàng)建一個對應的線程來處理,線程數量越多,上限文切換造成的資源損耗越大。在BIO中使用線程池,就意味著線程池中的維護的線程數就是server端支持最多有多少個client來連接。
NIO Buffer
一個Buffer對象是固定數量的數據的容器。其作用是一個存儲器或分段運輸區(qū),在這里數據可以被存儲并在之后用于檢索。對于每個非布爾原始數據類型都有一個緩沖區(qū)類。盡管緩沖區(qū)作用于他們存儲的原始數據類型,但緩沖區(qū)十分傾向于處理字節(jié)。緩沖區(qū)的工作與通道緊密聯系。通道是I/O傳輸發(fā)生是通過的入口,而緩沖區(qū)是這些數據傳輸的來源或目標。對于離開緩沖區(qū)的傳輸,是將緩沖區(qū)的數據傳送到通道。對于傳回緩沖區(qū)的傳輸,是將通道的數據放置在緩沖區(qū)中。這種在協(xié)同對象之間進行的緩沖區(qū)數據傳遞是高校數據處理的關鍵。
Buffer定義所有緩沖區(qū)類型共有的曹鄒,無論是它們所包含的數據類型還是可能具有的特定行為。
緩沖區(qū)是包在一個對象內的基本數據元素數組。Buffer類的優(yōu)點是他將關于數據的數據內容和信息包含在一個單一的對象中。Buffer類以及它專有的子類定義了一個用于處理數據緩沖的API。
public abstract class Buffer{
// mark <= position <= limit <= capacity
private int mark = -1;
private int position = 0';
private int limit;
private int capacity;
public final int capacity();
public final int position();
public final Buffer position(int newPosition);
public final int limit();
public final Buffer limit(int newLimit);
public final Buffer mark();
public final Buffer reset();
public final Buffer clear();
public final Buffer flip();
public final Buffer rewind();
public final int remaining();
public final boolean hasRemaining();
public abstract boolean isReadOnly();
public abstract boolean hasArray();
public abstract Object array();
public abstract int arrayOffset();
public abstract boolean isDirect();
}
容量(Capacity):緩沖區(qū)能夠容納的數據元素的最大數量,可以理解為數組的長度。在緩沖區(qū)創(chuàng)建時被設定,并且永不能改變
上界(Limit):緩沖區(qū)的第一個不能被讀或寫的元素的索引。或說緩沖區(qū)中現存元素的技數
位置(Position):下一個要被讀寫的元素的索引。Buffer類提供了get()和put()函數來讀取或存入數據,position位置會自動進行相應的更新
標記(Mark):一個備忘位置。調用mark()來設定mark = position。調用reset()設定position = mark。標記在設定前是未定義的。
public abstract class ByteBuffer{
public static ByteBuffer allocateDirect(int capacity);
public static ByteBuffer allocate(int capacity);
public static ByteBuffer wrap(byte[] array);
public static ByteBuffer wrap(byte[] array, int offset, int length);
public abstract byte get();
public abstract byte get(int index);
public abstract ByteBuffer put(byte b);
public abstract ByteBuffer put(int index, int b);
}
新的緩沖區(qū)是由分配(allocate)或包裝(wrap)操作創(chuàng)建的。allocate操作創(chuàng)建一個緩沖區(qū)對象并分配一個私有的空間來儲存容量大小的數據元素。wrap操作創(chuàng)建一個緩沖區(qū)對象但是不分配任何空間來儲存數據元素。它使用你所提供的的數組作為存儲空間來儲存穿沖去中的數據元素。
存儲操作時通過get和put操作進行的,get和put可以使相對的或是絕對的。相對方案是不帶有索引參數的函數。當相對函數被調用時,位置在返回時前進一。若位置前進過多,相對運算就會拋出異常。絕對存取不會影響緩沖區(qū)的位置屬性,但若提供的索引超出范圍,也將拋出IndexOutOfBoundsException異常。
flip()函數可以將position值重新設為0,同時將limit設置為當當前緩沖區(qū)內的最后一個元素的索引。rewind()將position設置為0單不會改變limit的值。
clear()函數可以讓緩沖區(qū)恢復到初始狀態(tài),但并不改變緩沖區(qū)中的任何數據元素。即position=0, limit=capacity,mark=-1。
mark()方法能使緩沖區(qū)記住一個position并在之后將其返回。緩沖區(qū)的標記在mark()行數被調用之前是未定義的,值為-1,調用時mark被設為當前的position的值。reset()函數將position設為當前的mark值。若mark未定義,調用reset()將導致InvalidMarkException異常。
compact()方法會將未讀數據元素需要下移以使第一個元素索引為0。
復制緩沖區(qū)
緩沖區(qū)的復制有兩種:
完全復制:調用duplicate()或asReadOnluBuffer()函數
部分復制:調用slice()
duolicate()函數創(chuàng)建了一個與原始緩沖區(qū)相似的新緩沖區(qū)。兩個緩沖區(qū)共享數據元素,擁有同樣的容量,但每個緩沖區(qū)擁有各自的位置,上界和標記屬性。對一個緩沖區(qū)的數據元素所做的改變會反映在另一個緩沖區(qū)上。若原始的緩沖區(qū)為只讀或直接緩沖區(qū),那新的緩沖區(qū)將繼承這些屬性。
CharBuffer buffer = CharBuffer.allocate(8); buffer.position(3).limit(6).mark().position(5); CharBuffer dupBuffer = buffer.duplicate(); buffer.clear();
asReadOnlyBuffer()函數來生成一個只讀的緩沖區(qū)視圖。這個新的緩沖區(qū)不允許使用put(),并且isReadOnly()會返回true。對這一只讀緩沖區(qū)調用put()函數會導致ReadOnlyBufferException異常
直接緩沖區(qū)
直接字節(jié)緩沖區(qū)通常是I/O操作最好的選擇。在設計方面,它們支持JVM可用的最高效I/O機制。非直接字節(jié)緩沖區(qū)可以被傳遞給通道,但這樣可能會導致性能損耗。通常非直接緩沖不可能成為一個本地I/O操作的目標。若向一個通道中傳遞一個非直接ByteBuffer對象用于寫入,通道可能會在每次調用中隱含地進行下面的操作:
1. 創(chuàng)建一個臨時的直接ByteBuffer對象
2. 將非直接緩沖區(qū)的內容復制到臨時緩沖區(qū)中
3. 使用臨時緩沖區(qū)執(zhí)行低層次I/O操作
4. 臨時緩沖區(qū)對象離開作用域,并最終成為被回收的無用數據
直接緩沖區(qū)是I/O的最佳選擇,但可能比創(chuàng)建非直接緩沖區(qū)要花費更高的成本。直接緩沖區(qū)使用的內存是通過調用給本地操作系統(tǒng)方面的代碼分配的,繞過了JVM堆棧。建立和銷毀直接緩沖區(qū)會明顯比具有堆棧的緩沖區(qū)更加破費,具體取決于操作系統(tǒng)和JVM的實現。直接緩沖區(qū)的內存區(qū)域不受無用存儲單元收集支配。
直接ByteBuffer是通過調用具有所需容量的ByteBuffer.allocateDirect()函數產生的。通常用wrap()函數所創(chuàng)建的被包裝的緩沖區(qū)總是非直接的。通過緩沖區(qū)的isDirect()方法來判斷是否是直接緩沖區(qū)。
讀取數據總是需要通過內核空間傳遞到用戶空間,而往外寫數據總是要通過用戶空間到內核空間。JVM堆棧屬于用戶空間。直接緩沖區(qū)就是內核空間。內核空間的存在java中是通過Unsafe這個類來調用的。
內存映射緩沖區(qū)
映射緩沖區(qū)是帶有存儲的文件,通過內存映射來存取數據元素的字節(jié)緩沖區(qū)。映射緩沖區(qū)通常是直接存取內存的,只能通過FileChannel類來創(chuàng)建。映射緩沖區(qū)的用法和直接緩沖區(qū)類似,但MappedByteBuffer對象可以獨立于文件存取形式的許多特定字符。
MappedByteBuffer在大文件處理方面性能比較好。
總結
- 上一篇: 安全工具(免费杀毒软件Avast、免费防
- 下一篇: 怎么创建具有真实纹理的CG场景岩石?