【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
最近在做通信和传输的项目,大量的使用NIO和Mina,虽然之前一直对这部分比较关注,但是还没有好好的总结一下这方面的内容。今天想写点儿NIO里最基本的一个类ByteBuffer。至于Mina中的IoBuffer,我们可以先看Mina API中的描述:
A byte buffer used by MINA applications. This is a replacement for ByteBuffer. Please refer to ByteBuffer documentation for preliminary usage。
当然,接下去也有写到:MINA does not use NIO ByteBuffer directly for two reasons,至于这Two Reasons,我们将在后面的比较中展开。
ByteBuffer继承了Buffer,对Buffer的理解可以说是NIO的入门。在Buffer中有4个重要的Attributes:
Capacity: the capacity is set when the buffer is created and can never be changed。
Limit: the first element of the buffer that should not be read or written
Position: the index of the next element to be read or written
Mark: a remembered position. Calling mark() set mark=position
他们的关系如下:0<=mark<=position<=limit<=capacity。
通俗的讲:
Capacity:开的内存的大小,一旦设定了,就不能更改了。注意,这里指的是原生的NIO。
Limit:可以分读写来统计。在写入buffer时,limit表示有多少空间可以写入。在从buffer写出时,limit表示有多少可以写出。
Position:下一个要被读或写的位置。
Mark:标记位,可以记住某个position,方便后续操作。
对于ByteBuffer有如下常用的操作:
flip()::读写模式的转换。
rewind() :将 position 重置为 0 ,一般用于重复读。
clear() :清空 buffer ,准备再次被写入 (position 变成 0 , limit 变成 capacity) 。
compact(): 将未读取的数据拷贝到 buffer 的头部位。
mark() 、 reset():mark 可以标记一个位置, reset 可以重置到该位置。
get()、getShort()等一系列get操作:获取ByteBuffer中的内容,当然这里get的内容都是从position开始的,所以要时刻注意position。每次get之后position都会改变。Position的变化是根据你get的类型,如果是short,那就是2个byte,如果是int,那就是增加4个byte,即32。
put()、putShort()等一系列put操作:向ByteBuffer添加内容,这里put的内容都是从position开始的。每次put之后position都会改变。
当然还有allocate、hasRemaining等常用的方法,不过这些用法一般都不会出错,使用起来和4个attributes也没有多大相关。特别注意:Buffers are not thread-safe. If you want to access a given buffer concurrently from multiple threads, you will need to do your own synchronization prior to accessing the buffer.至于Buffer或者ByteBuffer有什么用?那太多了,只要涉及到传输、涉及到通信,都可以用到。当然你也可以用它最原始的含义,缓冲。
好了NIO的ByteBuffer告一段落,接下来先说IoBuffer中说不用ByteBuffer的Two Reasons:
l It doesn't provide useful getters and putters such as fill, get/putString, and get/putAsciiInt() enough.
l It is difficult to write variable-length data due to its fixed capacity
看好了,对于第一点我想也没什么,增加了更实用的getString。关键是第二点,IoBuffer实现了Auto Expand和Auto Shrink。这就意味了,capacity可以根据传输内容的大小自动变更了。在使用上,我们可以这样写:
IoBuffer buf = IoBuffer.allocate(1024).setAutoExpand(true);
在
IoBuffer的源码中,大部分都使用了原生的
ByteBuffer来实现,这部分采用
allocator来实现。
/** The allocator used to create new buffers */
private static IoBufferAllocator allocator = new SimpleBufferAllocator();
在SimpleBufferAllocator的其中一段allocate:
public ByteBuffer allocateNioBuffer(int capacity, boolean direct) {
ByteBuffer nioBuffer;
if (direct) {
nioBuffer = ByteBuffer.allocateDirect(capacity);
} else {
nioBuffer = ByteBuffer.allocate(capacity);
}
return nioBuffer;
}
至于其他操作,和
ByteBuffer
类似。
贴一段Reilly - Java NIO中的一段代码作为结束,后续更多的Mina相关会根据开发进度给出介绍:
import java.nio.CharBuffer;
public class BufferFillDrain {
private static int index = 0;
private static String[] strings = { "A random string value",
"The product of an infinite number of monkeys",
"Hey hey we're the Monkees" };
private static boolean fillBuffer(CharBuffer buffer) {
if (index >= strings.length) {
return false;
}
String string = strings[index++];
for (int i = 0; i < string.length(); i++) {
buffer.put(string.charAt(i));
}
return true;
}
private static void drainBuffer(CharBuffer buffer){
while(buffer.hasRemaining()){
System.out.println(buffer.get());
}
System.err.println("");
}
public static void main(String[] args) {
CharBuffer buffer=CharBuffer.allocate(100);
while(fillBuffer(buffer)){
buffer.flip();
drainBuffer(buffer);
buffer.clear();
}
}
}
因为之前做笔记的时候用的都是英文,所以好多都没有翻译过来,更好的文档是官方的文档,谢谢观赏。
来源:oschina
链接:https://my.oschina.net/u/589742/blog/84876