01_NIO基本概念
【NIO的几个概念】
Buffer(缓冲区)
Channel(通道,管道)
Selector(选择器,多路复用器)
【Buffer】
Buffer是一个对象,它包括一些要写入或者要读取的数据。在NIO类库中加入Buffer对象,是NIO与原来BIO的一个重要区别。
在面向流的BIO中,可以将数据直接写入或读取到Stream对象中,在NIO库中,所有的数据都是用缓冲区Buffer处理的(读、写)。
缓冲区实质上是一个数组,通常它是一个字节数组(ByteBuffer),也可以使用其他类型的数组,这个数组为缓冲区提供了数据的访问读写等操作属性,如位置、容量、上限等概念(参考API文档)。
Buffer类型:最常用的是ByteBuffer,实际上每一种java基本类型都对应了一种缓冲区(除了Boolean类型)
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
【Buffer入门实例1——几个常用方法】
public class TestBuffer { public static void main(String[] args) {
//Buffer基本操作
//创建指定长度的缓冲区
IntBuffer buf = IntBuffer.allocate();
buf.put(); //position位置:0 -> 1
buf.put(); //position位置:1 -> 2
buf.put(); //position位置:2 -> 3
System.out.println("【当前buf状态】:"+buf);
//flip()把位置复位为0,也就是position位置 : 3 ->0
buf.flip();
System.out.println("使用flip()复位【当前buf状态】:"+buf);
System.out.println("容量为:"+buf.capacity());
System.out.println("限制为:"+buf.limit()); System.out.println("获取下标为1的元素"+buf.get());
System.out.println("get(index)方法,position位置不改变:"+buf); for(int i=; i<buf.limit(); i++){
//调用get()方法会使得buffer的缓冲区位置(position+1)向后递增一位
System.out.print(buf.get()+"\t");
}
System.out.println("\nbuf对象遍历之后为【当前buf状态】:"+buf);
} }
【运行结果】
【Buffer实例2——wrap()方法】
public static void main(String[] args) {
/**
* wrap方法的使用
* wrap方法会包裹一个数组:一般这种用法不会先初始化缓冲对象的长度,因为没有意义,最后还会别wrap所包裹的数组覆盖掉。
* 并且wrap方法修改缓冲区对象的时候,数组本身会跟着变化
**/
int arr[] = new int[]{,,};
IntBuffer buf1 = IntBuffer.wrap(arr);
System.out.println(buf1); IntBuffer buf2 = IntBuffer.wrap(arr,,);
//这样使用表示容量为数组arr的长度,但是可操作的元素只有实际进入缓冲区的元素长度
System.out.println(buf2);
}
【运行结果】
【buffer实例3——其他方法】
public static void main(String[] args) {
IntBuffer buf1 = IntBuffer.allocate();
int[] arr = new int[]{,,};
buf1.put(arr);
System.out.println("【当前buf1状态】:"+buf1); //一种复制方法
IntBuffer buf2 = buf1.duplicate();
System.out.println("【当前buf2状态】:"+buf2); buf1.flip();
System.out.println("buf1的可读数据:"+buf1.remaining()); int[] arr2 = new int[buf1.remaining()];
//将缓冲区的数据放入到arr2数组中
buf1.get(arr2);
for(int i : arr2){
System.out.print(Integer.toString(i) + ",");
}
}
【运行结果】
【channel】
channel(通道),就像自来水管一样,网络数据通过channel读取和写入,通道与流的不同之处是:通道是双向的,而流只是一个方向上移动(一个流必须是InputStream或OutputStream的子类),而通道可以用于读、写或者二者同时进行,最关键的是可以与多路复用器(Selector)结合起来,有多种的状态位置,方便多路复用器去识别。
事实上通道分为两大类:
1.用于网络读写——SelectorChannel
2.用于文件操作——FileChannel
一般使用的[ SocketChannel ] 和 [ ServerSocketChannel ] 都是SelectorChannel的子类。
【Selector】
Select(多路复用器),是NIO的基础,非常重要,Selector提供选择已经就绪的任务的能力。
简单说,就是Selector会不断地轮询注册在其上的通道(Channel),如果某个通道发生了读写操作,这个通道就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以取得就绪的Channel集合,从而进行后续的IO操作。
一个Selector可以负责成千上万的Channel通道,没有上限,这也是JDK使用了epoll代替了传统的Selector实现,获得连接句柄没有限制,这也就以为着我们只要一个线程负责Selector的轮询,就可以接入成千上万的客户端,这是JDK NIO库的巨大进步。
Selector线程就类似一个管理者(Master),管理了成千上万个通道,然后轮询那个管道的数据已经准备好,通知cpu执行IO的读取或写入操作。
Selector模式:当IO事件(管道)注册到选择器以后,selector会分配给每个管道一个key值,相当于标签。Selector选择器是以轮询的方式进行查找注册的所有IO事件(管道),当我们的IO事件(管道)准备就绪后,Selector就会识别,会通过key值来找到对应的管道,进行相关的数据操作(即从管道里读或写操作,写到我们的缓冲区中)。
每个Channel(管道)都会对Selector进行不同的时间基础,以便选择器查找:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
01_NIO基本概念的更多相关文章
- 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念
一.前言 DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...
- 【Machine Learning】机器学习及其基础概念简介
机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
- 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之集群概念介绍(一)
集群概念介绍(一)) 白宁超 2015年7月16日 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习 ...
- 声音分贝的概念,dBSPL.dBm,dBu,dBV,dBFS
需要做个音频的PPM表,看着一堆的音频术语真是懵了,苦苦在网上扒了几天的文档,终于有了点收获,下面关于声音的分贝做个总结. 分贝 Decibel 分贝(dB)是一个对数单位(logarithmic u ...
- js面向对象学习 - 对象概念及创建对象
原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...
- 【Linux大系】Linux的概念与体系
感谢原作者:Vamei 出处:http://www.cnblogs.com/vamei 我在这一系列文章中阐述Linux的基 本概念.Linux操作系统继承自UNIX.一个操作系统是一套控制和使用计算 ...
- KOTLIN开发语言文档(官方文档) -- 2.基本概念
网页链接:https://kotlinlang.org/docs/reference/basic-types.html 2. 基本概念 2.1. 基本类型 从可以在任何变量处理调用成员函数和属性 ...
- .NET面试题系列[5] - 垃圾回收:概念与策略
面试出现频率:经常出现,但通常不会问的十分深入.通常来说,看完我这篇文章就足够应付面试了.面试时主要考察垃圾回收的基本概念,标记-压缩算法,以及对于微软的垃圾回收模板的理解.知道什么时候需要继承IDi ...
- 《徐徐道来话Java》(1):泛型的基本概念
泛型是一种编程范式(Programming Paradigm),是为了效率和重用性产生的.由Alexander Stepanov(C++标准库主要设计师)和David Musser(伦斯勒理工学院CS ...
随机推荐
- JQuery的get、post、ajax方法
1.jQuery $.get() 方法 $.get() 方法通过 HTTP GET 请求从服务器上请求数据. jQuery.get( url, [data], [callback] ): 参数: ...
- rest-assured之验证响应数据(Verifying Response Data)
前面的文章中已经介绍过了如果获得响应数据,接下来我们来介绍一下应该如何来验证这些获得的响应数据,比如验证状态码.状态行.cookies.header.content-type以及body体. 1.验证 ...
- POJ_1990 MooFest 【树状数组】
一.题面 POJ1990 二.分析 一个简单的树状数组运用.首先要把样例分析清楚,凑出57,理解一下.然后可以发现,如果每次取最大的v就可以肆无忌惮的直接去乘以坐标差值就可以了,写代码的时候是反着来的 ...
- Eureka 高可用 - 踩坑回忆
1.application.yml中eureka配置更改 ## Eurake 公用配置 ## 向其他注册中心注册 eureka.client.register-with-eureka=true ## ...
- odoo 二次开发的方法
介绍 二开时模型创建完毕并配好视图后对于基本的CRUD操作不需要再在代码中实现,框架会自动提供这些功能,但如果我们的开发需求不仅仅是对当前对象的CRUD时,就需要在框架原来方法的基础上扩展出一些自己所 ...
- redis中算法之——MurmurHash2算法
MurmurHash算法由Austin Appleby发明于2008年,是一种非加密hash算法,适用于基于hash查找的场景.murmurhash最新版本是MurMurHash3,支持32位,64位 ...
- Spring异常:Annotation-specified bean name.. for bean class ...
Spring重命名问题.对照项目中的注解,查找@Service是否重重名.由于Spring是在注解下按配置扫描的方式去创建对象的,那么两个重名的注解也就不成立了. 备注,特别注意test包下有没有通过 ...
- java实现多线程的4种方式
1.继承Thread类 看jdk源码可以发现,Thread类其实是实现了Runnable接口的一个实例,继承Thread类后需要重写run方法并通过start方法启动线程. 继承Thread类耦合性太 ...
- 我的Python升级打怪之路【五】:Python模块
模块,是一些代码实现了某个功能的集合 模块的分类: 自定义模块 第三方模块 内置模块 导入模块 import module from module.xx.xx import xx from modul ...
- unity2018的坑点
发布后有的电脑无法运行exe程序(反正我的电脑不行) 删除发布出来的一个叫UnityCrashHandler64.exe即可运行