基本概念
- 缓冲区的操作
用户空间缓冲区
内核空间缓冲区
DMA
用户空间相对于内核空间的限制
-发散汇聚
-
虚拟内存
物理内存与虚拟内存,以及分页 -
内存页面调度
也缺失,导致系统调用
缓存区
缓冲区就是一个对象,其中有一个数组字段用来存储基本数据元素(除了Boolean),另外有四个属性表示当前读写状态。
Capacity
Limit
Position
Mark
0<=Mark<=Position<=Limit<=Capcatiy
offset
ByteBuffer
get
put
flip
rewind
clear
hasRemaing
remaing
compact
reset
mark
equals
compareTo
批量移动
wrap
allocate
复制,视图
duplicate
slice
asReadOnlyBuffer
字节缓冲区
allocateDirect
字节顺序(endian-ness)
直接缓冲区:JVM 堆外内存
字节缓冲区域其他缓冲区的区别:
字节缓冲区的字节顺序是可以改变的,其他缓冲区不行
只有字节缓冲区可以作为通道的源或目标
为什么要有直接缓冲区
非直接字节缓冲区的内存不一定是连续的,而底层IO操作需要连续内存,所以出现了直接缓冲区,即使给通道的是非直接缓冲区,在使用的时候也是会创建一个临时直接缓冲区。
除了字节缓冲区有直接缓冲区,其他类型的缓冲区都没有直接缓冲区,但是可以作为直接字节缓冲区的视图缓冲区。
缓冲区视图
数据元素视图
通道
通道主要有两类:文件通道和套接字通道
FileChannel
SocketChannel/ ServerSocketChannel / DatagramChannel
通道既可以是单向的也可以是双向的,具体看实现了那几个接口
ReadableByteChannel
WriteableByteChannel
通过FileInputStream 打开的通道是只读的,即使该通道实现了WriteableByteChannel 接口
RandomAccessFile file = new RandomAccessFile("abc.csv", "r");
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
FileChannel channel = file.getChannel();
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);
int read = channel.read(buffer);
while (read != -1) {
buffer.flip();
decoder.decode(buffer, charBuffer, false);
charBuffer.flip();
System.out.println(charBuffer);
buffer.compact();
read = channel.read(buffer);
}
通道有阻塞和非阻塞模式,只有面向流的 scokets
和 pipes
才能使用非阻塞模式
将非阻塞和选择器组合实现多路复用IO
与缓冲区不同,通道不能被重复使用
通道的 close 方法是阻塞的,具体时间取决于关闭底层IO服务
关闭通道
如果一个现在被通道阻塞,中断该线程,对应的通道也会关闭
此外如果一个线程被中断,再去读通道,通道会关闭
实现了 InterruptibleChannel 接口的通道,在任何时候都可以关闭,即使有线程在该通道上面阻塞。
Scatter/Gather (本地矢量IO)
ScatteringByteChannel
GatheringByteChannel
public class Marketing {
private static final String DEMOGRAPHIC = "abc.txt";
// These are just representative; add your own
private static String[] col1 = {
"Aggregate", "Enable", "Leverage",
"Facilitate", "Synergize", "Repurpose",
"Strategize", "Reinvent", "Harness"
};
private static String[] col2 = {
"cross-platform", "best-of-breed", "frictionless",
"ubiquitous", "extensible", "compelling",
"mission-critical", "collaborative", "integrated"
};
private static String[] col3 = {
"methodologies", "infomediaries", "platforms",
"schemas", "mindshare", "paradigms",
"functionalities", "web services", "infrastructures"
};
private static String newline = System.getProperty("line.separator");
private static Random rand = new Random();
public static void main(String[] args) throws IOException {
int reps = 10;
if (args.length > 0) {
reps = Integer.parseInt(args[0]);
}
FileOutputStream outputStream = new FileOutputStream(DEMOGRAPHIC);
FileChannel channel = outputStream.getChannel();
ByteBuffer[] buffers = utterBS(reps);
while (channel.write(buffers) > 0) {
}
outputStream.close();
channel.close();
FileInputStream inputStream = new FileInputStream(DEMOGRAPHIC);
FileChannel channel1 = inputStream.getChannel();
Arrays.stream(buffers).forEach(Buffer::clear);
while (channel1.read(buffers) > 0) {
}
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer;
for (ByteBuffer readBuffer : buffers) {
charBuffer = CharBuffer.allocate(readBuffer.limit());
readBuffer.flip();
decoder.decode(readBuffer, charBuffer, false);
charBuffer.flip();
System.out.println(charBuffer);
}
System.out.println("All Buffer Data has write to file");
}
public static ByteBuffer[] utterBS(int howMany) {
List<ByteBuffer> buffers = new LinkedList<>();
for (int i = 0; i < howMany; i++) {
buffers.add(pickRandom(col1, " "));
buffers.add(pickRandom(col2, " "));
buffers.add(pickRandom(col3, newline));
}
ByteBuffer[] byteBuffers = new ByteBuffer[buffers.size()];
buffers.toArray(byteBuffers);
return byteBuffers;
}
public static ByteBuffer pickRandom(String[] strings, String suffix) {
String string = strings[rand.nextInt(strings.length)];
byte[] bytes = string.getBytes();
byte[] bytes1 = suffix.getBytes();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bytes.length + bytes1.length);
byteBuffer.put(bytes);
byteBuffer.put(bytes1);
byteBuffer.flip();
return byteBuffer;
}
}
- 文件通道
阻塞的,相对网络通道延时比较少
创建方式:
RandomAccessFile
FileInputStream
FileOutputStream
FileChannel 类保证同一Java 虚拟机上的所有实例看到的某个文件的视图是一直的。
FileChannel 是线程安全的
position 表示接下来文件读或写的位置,由channel 和 文件描述符共享
网友评论