标签:ring code ati 抽象 eof capacity written moved data-
Buffer是一个抽象类,位于java.nio包中,主要用作缓冲区。注意:Buffer是非线程安全类。
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
NIO 有以下几种Buffer类型:
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
capacity一旦初始化
后就不会改变,其值一直为常量。在使用中我们一般使用Buffer的抽象子类ByteBuffer.allocate()方法,实际上是生成ByteArrayBuffer类。
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1。
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0。当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
在读模式下,Buffer的limit表示你最多能从Buffer里读多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
/** * <code>UNSET_MARK</code> means the mark has not been set. */ static final int UNSET_MARK = -1; /** * The capacity of this buffer, which never changes. */ final int capacity; /** * <code>limit - 1</code> is the last element that can be read or written. * Limit must be no less than zero and no greater than <code>capacity</code>. */ int limit; /** * Mark is where position will be set when <code>reset()</code> is called. * Mark is not set by default. Mark is always no less than zero and no * greater than <code>position</code>. */ int mark = UNSET_MARK; /** * The current position of this buffer. Position is always no less than zero * and no greater than <code>limit</code>. */ int position = 0; /** * The log base 2 of the element size of this buffer. Each typed subclass * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this * value. The value is used by JNI code in frameworks/base/ to avoid the * need for costly ‘instanceof‘ tests. */ final int _elementSizeShift; /** * For direct buffers, the effective address of the data; zero otherwise. * This is set in the constructor. */ final long effectiveDirectAddress;
/** * <code>UNSET_MARK</code> means the mark has not been set. */ static final int UNSET_MARK = -1; /** * Clears this buffer. * <p> * While the content of this buffer is not changed, the following internal * changes take place: the current position is reset back to the start of * the buffer, the value of the buffer limit is made equal to the capacity * and mark is cleared. * * @return this buffer. */ public final Buffer clear() { position = 0; //设置当前下标为0 mark = UNSET_MARK; //取消标记 limit = capacity; //设置写越界位置与和Buffer容量相同 return this; }
/** * Sets this buffer‘s mark at its position. * * @return This buffer */ public final Buffer mark() { mark = position; return this; } /** * Resets the position of this buffer to the <code>mark</code>. * * @return this buffer. * @throws InvalidMarkException * if the mark is not set. */ public final Buffer reset() { if (mark == UNSET_MARK) { throw new InvalidMarkException("Mark not set"); } position = mark; return this; }
/** * Rewinds this buffer. * <p> * The position is set to zero, and the mark is cleared. The content of this * buffer is not changed. * * @return this buffer. */ public final Buffer rewind() { position = 0; mark = UNSET_MARK; return this; }
/** * Flips this buffer. * <p> * The limit is set to the current position, then the position is set to * zero, and the mark is cleared. * <p> * The content of this buffer is not changed. * * @return this buffer. */ public final Buffer flip() { limit = position; position = 0; mark = UNSET_MARK; return this; }
/** * Returns the number of remaining elements in this buffer, that is * {@code limit - position}. * * @return the number of remaining elements in this buffer. */ public final int remaining() { return limit - position; }
/** * Compacts this byte buffer. * <p> * The remaining bytes will be moved to the head of the * buffer, starting from position zero. Then the position is set to * {@code remaining()}; the limit is set to capacity; the mark is * cleared. * * @return {@code this} * @throws ReadOnlyBufferException * if no changes may be made to the contents of this buffer. */ public abstract ByteBuffer compact();
当满足下列条件时,表示两个Buffer相等:
equals只是比较Buffer的一部分,不是每一个在它里面的元素都比较(即它只比较Buffer中的剩余元素)。
以ByteBuffer为例
/** * Tells whether or not this buffer is equal to another object. * * <p> Two byte buffers are equal if, and only if, * * <ol> * * <li><p> They have the same element type, </p></li> * * <li><p> They have the same number of remaining elements, and * </p></li> * * <li><p> The two sequences of remaining elements, considered * independently of their starting positions, are pointwise equal. * </p></li> * * </ol> * * <p> A byte buffer is not equal to any other type of object. </p> * * @param ob The object to which this buffer is to be compared * * @return <tt>true</tt> if, and only if, this buffer is equal to the * given object */ public boolean equals(Object ob) { if (this == ob) return true; if (!(ob instanceof ByteBuffer)) return false; ByteBuffer that = (ByteBuffer)ob; if (this.remaining() != that.remaining()) return false; int p = this.position(); for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) if (!equals(this.get(i), that.get(j))) return false; return true; }
compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:
以ByteBuffer为例
/** * Compares this buffer to another. * * <p> Two byte buffers are compared by comparing their sequences of * remaining elements lexicographically, without regard to the starting * position of each sequence within its corresponding buffer. * Pairs of {@code byte} elements are compared as if by invoking * {@link Byte#compare(byte,byte)}. * * <p> A byte buffer is not comparable to any other type of object. * * @return A negative integer, zero, or a positive integer as this buffer * is less than, equal to, or greater than the given buffer */ public int compareTo(ByteBuffer that) { int n = this.position() + Math.min(this.remaining(), that.remaining()); for (int i = this.position(), j = that.position(); i < n; i++, j++) { int cmp = compare(this.get(i), that.get(j)); if (cmp != 0) return cmp; } return this.remaining() - that.remaining(); }
由于ByteBuffer是非线程安全的,所以多线程访问的时候也必须加锁。
ByteBuffer在内部也是利用byte[]作为内存缓冲区,只不过多提供了一些标记变量而已。当多线程访问的时候,可以清楚的知道当前数据的位置。
标签:ring code ati 抽象 eof capacity written moved data-
原文地址:http://www.cnblogs.com/yixiu868/p/8011404.html