Buffer的数据存取

   一个用于特定基本数据类行的容器。有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类。

  Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通道读入到缓冲区,从缓冲区写入通道中的。

  Buffer就像一个数组,可以保存多个相同类型的数据。根据类型不同(boolean除外),有以下Buffer常用子类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer

Buffer的概述

1)容量(capacity):表示Buffer最大数据容量,缓冲区容量不能为负,并且建立后不能修改。

2)限制(limit):第一个不应该读取或者写入的数据的索引,即位于limit后的数据不可以读写。缓冲区的限制不能为负,并且不能大于其容量(capacity)。

3)位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制(limit)。

4)标记(mark)与重置(reset):标记是一个索引,通过Buffer中的mark()方法指定Buffer中一个特定的position,之后可以通过调用reset()方法恢复到这个position。

public class Test {

	public static void main(String[] args) {
// 1.指定缓冲区大小1024
ByteBuffer buf = ByteBuffer.allocate(1024);
System.out.println("--------------------");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
// 2.向缓冲区存放5个数据
buf.put("abcd1".getBytes());
System.out.println("--------------------");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
// 3.开启读模式
buf.flip();
System.out.println("----------开启读模式...----------");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
byte[] bytes = new byte[buf.limit()];
buf.get(bytes);
System.out.println(new String(bytes, 0, bytes.length));
System.out.println("----------重复读模式...----------");
// 4.开启重复读模式
buf.rewind();
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
byte[] bytes2 = new byte[buf.limit()];
buf.get(bytes2);
System.out.println(new String(bytes2, 0, bytes2.length));
// 5.clean 清空缓冲区 数据依然存在,只不过数据被遗忘
System.out.println("----------清空缓冲区...----------");
buf.clear();
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
System.out.println((char)buf.get());
} }
  • make与rest用法
public class Test01 {

	public static void main(String[] args) {
ByteBuffer buf = ByteBuffer.allocate(1024);
String str = "abcd1";
buf.put(str.getBytes());
// 开启读取模式
buf.flip();
byte[] dst = new byte[buf.limit()];
buf.get(dst, 0, 2);
buf.mark();
System.out.println(new String(dst, 0, 2));
System.out.println(buf.position());
buf.get(dst, 2, 2);
System.out.println(new String(dst, 2, 2));
System.out.println(buf.position());
buf.reset();
System.out.println("重置恢复到mark位置..");
System.out.println(buf.position());
} }

通道Channel

  1. 通道可以同时进行读写,而流只能读或者只能写

  2. 通道可以实现异步读写数据

  3. 通道可以从缓冲读数据,也可以写数据到缓冲:

  • 分散读取与聚集写入

    分散读取:将通道中的数据分散到多个缓冲区中



    聚集写入:将多个缓冲区的数据聚集到通道中

直接缓冲区与非直接缓冲区别

  • 非直接缓冲区:通过 allocate() 方法分配缓冲区,将缓冲区建立在 JVM 的内存中

// 1.利用通道完成文件的复制(非直接缓冲区)
static public void test1() throws IOException { // 4400
long start = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("e://1.jpg");
FileOutputStream fos = new FileOutputStream("e://2.jpg");
// ①获取通道
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel();
// ②分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
while (inChannel.read(buf) != -1) {
buf.flip();// 切换为读取数据
// ③将缓冲区中的数据写入通道中
outChannel.write(buf);
buf.clear();
}
outChannel.close();
inChannel.close();
fos.close();
fis.close();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
  • 直接缓冲区:通过 allocateDirect() 方法分配直接缓冲区,将缓冲区建立在物理内存中。可以提高效率

// 使用直接缓冲区完成文件的复制(内存映射文件)
static public void test2() throws IOException {
long start = System.currentTimeMillis();
FileChannel inChannel = FileChannel.open(Paths.get("e://1.jpg"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("e://2.jpg"), StandardOpenOption.WRITE,
StandardOpenOption.READ, StandardOpenOption.CREATE);
// 内存映射文件
MappedByteBuffer inMappedByteBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedByteBuffer = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
// 直接对缓冲区进行数据的读写操作
byte[] dsf = new byte[inMappedByteBuf.limit()];
inMappedByteBuf.get(dsf);
outMappedByteBuffer.put(dsf);
inChannel.close();
outChannel.close();
long end = System.currentTimeMillis();
System.out.println(end - start);
}

Selector

一个组件,可以检测多个NIO channel,看看读或者写事件是否就绪。

多个Channel以事件的方式可以注册到同一个Selector,从而达到用一个线程处理多个请求成为可能。

非阻塞IO数据准备就绪之后,由选择器发通知给服务器端,数据在准备之前服务器无需等待

NIO的缓冲区、通道、选择器关系理解的更多相关文章

  1. Java NIO之Selector(选择器)

    历史回顾: Java NIO 概览 Java NIO 之 Buffer(缓冲区) Java NIO 之 Channel(通道) 其他高赞文章: 面试中关于Redis的问题看这篇就够了 一文轻松搞懂re ...

  2. java输入输出 -- java NIO之文件通道

    一.简介 通道是 Java NIO 的核心内容之一,在使用上,通道需和缓存类(ByteBuffer)配合完成读写等操作.与传统的流式 IO 中数据单向流动不同,通道中的数据可以双向流动.通道既可以读, ...

  3. 类之间关系理解:组合>聚合>关联>依赖;实现,继承

    类之间关系理解:组合>聚合>关联>依赖:实现,继承 1. 从类之间的关系来看,不外乎以下几种 组合>聚合>关联>依赖:实现,继承 且可以分为以下两类: (1)实现, ...

  4. [转]Shared——React Native与原生关系理解与对比

    零.关系理解 这个是我对RN和原生关系的理解.简单解释下这个图. RN js编写完业务代码后,通过react-native bundle命令,将代码分别编译成一个index.ios.bundle和in ...

  5. go语言从例子开始之Example26.通道选择器

    Go 的通道选择器 让你可以同时等待多个通道操作.Go 协程和通道以及选择器的结合是 Go 的一个强大特性. Example: package main import "time" ...

  6. 027_go语言中的通道选择器

    代码演示 package main import "fmt" import "time" func main() { c1 := make(chan strin ...

  7. nio之缓冲区(Buffer)理解

    一.缓冲区简介 Nio中的 Buffer 是用于存储特定基础类型的一个容器.为了能熟练的使用 Nio中的各种 Buffer , 我们需要理解 Buffer 中的 三个重要 的属性. 1. capaci ...

  8. NIO之缓冲区

    NIO引入了三个概念: Buffer 缓冲区 Channel 通道 selector 选择器 1.java.io优化建议 操作系统与Java基于流的I/O模型有些不匹配.操作系统要移动的是大块数据(缓 ...

  9. Java NIO(六)选择器

    前言 Selector选择器是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样使得一个单独的线程可以管理多个Channel,从而管理多个网络连接.选择 ...

随机推荐

  1. Leetcode 12. Integer to Roman(打表,水)

    12. Integer to Roman Medium Roman numerals are represented by seven different symbols: I, V, X, L, C ...

  2. andriod工程项目总结

    1,胡萝卜农场项目 (1)图片缓存项目 (2)android开源框架的尝试 2,智能厨房项目 (1)将所有网络请求防止到一个service中的思路 (2)左右导航的实现 (3)fragment的使用 ...

  3. windows编程,消息函数中拦截消息的问题

    很多年没有写windows窗口程序了,今天自制基于vulkan的程序时遇到了一些问题,部分代码如下: LRESULT CALLBACK XWindow::WndProc(HWND hWnd, UINT ...

  4. Android操作系统中11种传感器的介绍【转】

    本文转载自:http://www.oschina.net/question/163910_28354 在Android2.3 gingerbread系统中,google提供了11种传感器供应用层使用. ...

  5. codeforces 668C - Little Artem and Random Variable

    题目链接:http://codeforces.com/contest/668/problem/C --------------------------------------------------- ...

  6. vmware 虚拟 CPU 性能计数器事件与主机 CPU 不兼容。

    错误提示:虚拟 CPU 性能计数器事件与主机 CPU 不兼容. 点放弃 如果是暂时状态选关机, 丢失掉运行状态,即可保留硬盘内容重新开机

  7. 使用GOGS搭建自己的Git托管

    大家在开发中一般使用的git服务都是公司搭建好的,或者就是直接用gayhub提供的免费的仓库 如果想搭建一个自己的仓库的话怎么弄,这里给大家安利一款开箱即用的git托管服务:gogs. gogs是基于 ...

  8. 山西汽车销量(hive)

    1.创建数据库create database db_cart; 2.使用数据库use db_cart; 3.创建表create table t_cart(province STRING,month I ...

  9. 【MM系列】SAP MM模块-委外采购订单 把Warning转换成Error信息提示

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM模块-委外采购订单 把W ...

  10. chineseocr项目的配置阶段出现的问题及解决方案

    chineseocr为GitHub上的一个开源项目,主要使用yolos,crnn等深度学习框架训练好后的模型使用.测试结果发现,不管是针对文本文件.表格文件.还是场景图,如身份证火车票,识别效果都比较 ...