NIO核心框架介绍

 NIO共引入了4个概念: 
- 缓存区:表示数据存放的容器,提供可读写的数据缓存区; 
- 字符集:用来对缓存数据进行解码和编码,在字节和Unicode字符之间转换; 
- 通道:用来接收或发送数据,提供与文件、套接字等的连接,类似于Java IO中的流; 
- 选择器:他们与可选择通道一起定义了多路的、无阻塞的IO设施。 
NIO框架位于Java.nio包中,它为每一个概念都提供了核心的支持类: 
- 缓存区Buffer:包括ByteBuffer,Mapped 
- ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,ShortBuffer,IntBuffer,LongBuffer; 
- 字符集Charset:java.nio.charset包中定义了字符集API,包括字符集Charset,编码器CharsetEncoder,解码器CharsetDecoder; 
- 通道Channel:java.nio.channels包中定义了通道API,包括文件通道Filechannel,Socket通道SocketChannel,ServerSocket通道ServerSocketChannel,数据包通道DatagramChannel; 
- 选择器Selector:包括选择器Selector和事件对象SelectionKey。

下面来了解着4个概念的含义和作用,并了解各个类包的接口和类的使用:

1. 缓存区Buffer: 
   传统的IO不断浪费对象资源,NIO通过使用缓存区读写数据避免了资源浪费。缓存区是一个数据容器,就可以把它看作内存中的一个大的数组,用来存放来自Channel的同一类型的所有数据,因此我们可以使用字节、字符、整数等缓存区。字节缓存区提供必要的方法,可以提取或存入所有基本类型(boolean型除外)的数据。 
  每个非布尔基本类型都有一个缓存区类,包括ByteBuffer,MappedByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,ShortBuffer,IntBuffer,Longbuffer。每个类定义了一系列用于将数据移除或移入缓存区中get()和put()方法,用于压缩、复制和切片缓存区的方法,以及用于分配新缓存区和将现有数组包装到缓存区中的静态方法。 
  所有的缓存区类都有一个统一的抽象父类Buffer,它代表了一块内存区域,可以执行一些与内存有关的操作,如清除其中的内容,支持读写或只读等操作。该类提供了共有的4个属性和3个操作。下面详细看看这些属性和操作的含义和使用方法,然后详细了解8个实现类的使用。 
①Buffer缓存区的4个基本属性: 
Buffer是个抽象类,它的基本属性包括容量capacity、限制limit、位置position、标记mark。 
a、capacity:这个Buffer最多能放多少数据,capacity一般在Buffer被创建的时候指定,取得容量的方法如下:

int capacity(); //返回此缓存区的容量

b、limit:在Buffer上进行的读写操作都不能越过这个下标。当写数据到Buffer中时,limit一般和capacity相等,当读数据时,limit代表Buffer中有效数据的长度,取得和修改限制的方法如下:

int limit();//返回此缓存区的限制
Buffer limit(int newLimit);//设置此缓存区的限制

c、position:读写操作的当前下标。当使用Buffer的相对位置进行读写操作时,读写会从这个下标进行,并在快操作完成后,Buffer会更新下标的值,取得和修改位置的方法如下:

int position(); //返回此缓存区的位置
BufferPosition(int newPosition);//设置此缓存区的位置

d、mark:一个临时存放的位置下标。调用mark()会将mark设为当前的position值,以后调用reset()会将position属性设置为mark的值。mark的值总是小雨等于position的值,如果将position的值设得比mark小,当前的mark值会被抛弃掉,可以使用下面的方法随时设置一个标记:

Buffer mark();//在此缓存区的位置设置标记

这些属性总是满足以下条件: 
0<=mark<=position<=limit<=capacity 
因此,标记、位置、限制和容量值遵守以下不变式: 
0<=标记<=位置<=限制<=容量 
对初始化的Buffer来说,position为0,limit=capacity。 
②Buffer缓存区的3个数据操作: 
a、清除clear():把position设为0,把limit设为capacity,一般在把数据写入Buffer前调用:

Buffer clear();//清除此缓存区

b、反转flip():把limit设为当前position,把position设为0,一般在从Buffer读取出数据前调用:

Buffer flip();//反转此缓存区

c、重绕rewind():把position设为0,limit不变,一般在把数据重新写入Buffer前调用

Buffer rewind();//重绕此缓存

Buffer对象有可能是只读的,这时任何对该对象的写操作都会触发一个ReadOnlyBufferException。isReadOnly()方法可以用来判断一个Buffer是否只读。 
③Buffer缓存区的8个实现类: 
对于每个非boolean基本类型,都有一个Buffer子类与之对应,这些子类位于包java.nio.Buffer中,他们的类关系图如下: 
Buffer类关系图

2.字符集Charset——编码与解码 
  向ByteBuffer中存放数据涉及到两个问题:字节的顺序和字符转换。ByteBuffer内部通过ByteOrder类处理了字节顺序问题,但是没有处理字符转换。事实上,ByteBuffer没有提供读写String。 
  java.nio.charset.Charset处理了字符转换问题。它通过构造java.nio.charset.CharsetEncoder和java.nio.charset.CharsetDecoder将字符序列CharBuffer转换成字节ByteBuffer和逆转换。当需要将CharBuffer存放的数据编码成ByteBuffer时,再将ByteBuffer里存的数据解码成CharBuffer,这时候就要用到CharsetEncoder和CharsetDecoder了。 
  CharsetDecoder用来将ByteBuffer解码为CharBuffer类型,CharsetEncoder用来将CharBuffer解码为ByteBuffer类型,其中的编码器和解码器都是通过Charset来创建的,它们之间关系如下: 
字符转换过程 
3.通道Channel 
现有的java.io类中没有能够读写Buffer类型,所以NIO提供了Channel通道类来读写Buffer。Channel是一个连接,可用于接收或发送数据,如文件和套接字。因为channel连接的是底层的物理设备,它可以直接支持设备的读写,或提供文件锁。对于文件、管道、套接字都存在相应的Channel类。 
  可以把Channel看成是数据流的替代品,它还通过Selector和SelectableChannel这两个类定义了一个进行非阻塞IO操作的API,这对需要高性能IO的应用非常重要。所有的Channel类都位于java.nio.channels包中,如下描述java.nio.channels中类和接口的关系: 
Channel类关系图 
图中最下面的4个类为具体的实现类。共包括7个接口类、3个抽象类和4个实现类。 
接口类: 
该图中包含了一系列的接口,用以分别实现不同的功能封装: 
①Channel是最顶层的接口,代表一个可以进行IO操作的通道; 
②ReadableByteChannel和WritableByteChannel分别提供对通道读取和写入ByteBuffer数据的功能; 
③ByteChannel用来将读取和写入的功能合并; 
④ScatteringByteChannel和GatheringByteChannel分别提供了批量读取和写入ByteBuffer数组的能力; 
⑤InterruptibleChannel提供多线程异步关闭的能力,它覆盖了Channel接口中的关闭方法close(),这表现在两方面: 
a、实现此接口的通道是可异步关闭的:如果某个线程阻塞于科终端通道上的IO操作,则另一个线程可调用该通道的close方法,这将导致已阻塞线程接收到AsynchronousCloseException, 
b、实现此接口的通道也是可中断的:如果某个线程阻塞于科中断通道上的IO操作中,则另一个线程可调用该阻塞线程的interrupt方法。这将导致该通道被关闭,已阻塞线程接收到CloseByInterruptException,并且设置阻塞线程的中断状态。 
  因此要拥有读写功能可以实现ByteChannel接口;要拥有批量读写功能,可以实现ScatteringByteChannel和GatheringByteChannel接口。从上图可看出,FileChannel、DatagramChannel、SocketChannel实现了这3个接口,因此它们都拥有批量读写的功能。 
抽象类: 
①AbstractInterruptibleChannel提供了可中断通道的基本实现,该类封装了实现通道异步关闭和中断所需的最低级别机制。在调用可能无限期阻塞的IO操作之前和之后,具体的通道类必须分别调用begin()和end()方法; 
②SelectableChannel则提供了可通过Selector实现多路复用的通道:该抽象类是所有支持非阻塞IO操作的channel的父类。SelectableChannel可以通过register()方法注册到一个或多个Selector,以进行非阻塞IO操作,此方法返回一个表示该通道已向选择器注册的心SelectionKey对象。SelectableChannel还可以选择阻塞和非阻塞模式,这就是NIO非阻塞编程的核心。所有Channel创建的时候都是阻塞模式,只有非阻塞的SelectableChannel才可以参与非阻塞IO操作,可以使用下面方法来设置和查看阻塞模式:

SelectableChannel configureBlocking(boolean block); //设置blocking模式
boolean isBlocking();  //返回blocking模式

③AbstractSelectableChannel则提供了SelectableChannel中抽象函数的实现。此类定义了处理SelectableChannel通道注册、注销和关闭机制的各种方法。它会维持此通道的当前阻塞模式及其当前的选择键集。; 
这三级抽象类都实现了InterruptibleChannel接口,所以也拥有多线程下异步关闭的能力。

转发:https://blog.csdn.net/luliuliu1234/article/details/61915000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423442.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(16):跳转链接小练习

点击图片实现跳转 目录结构 header.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv&q…

云开发的数据库权限机制解读丨云开发101

在使用云开发进行开发时&#xff0c;数据库权限是一个让不少人困扰的部分&#xff0c;四种数据库权限&#xff0c;到底是什么意思&#xff1f;其各自的权限、应用场景都是什么&#xff1f;大多数人对于这个机制&#xff0c;还是模糊的。为了帮助大家进行更好的开发&#xff0c;…

jremind V0.1.3.0添加透明

这次就把弹出消息的窗口改成了透明&#xff0c;本来说是做鼠标穿透的&#xff0c;给做成了透明&#xff0c;先用着&#xff01;有时间了再改了。 转载于:https://www.cnblogs.com/joypen/archive/2009/05/11/1693125.html

Java中的NIO非阻塞编程

在JDK1.4以前&#xff0c;Java的IO操作集中在java.io这个包中&#xff0c;是基于流的阻塞API。对于大多数应用来说&#xff0c;这样的API使用很方便&#xff0c;然而&#xff0c;一些对性能要求较高的应用&#xff0c;尤其是服务端应用&#xff0c;往往需要一个更为有效的方式来…

Nginx----基础

静态资源服务 通过本地文件系统提供服务&#xff1a;对css&#xff0c;js文件&#xff0c;图片等静态文件 反向代理服务 缓存&#xff1a;将一些数据经常不变的&#xff0c;缓存到Nginx中&#xff0c;直接给用户提供服务 负载均衡 api服务 OpenResty 数据库的服务比较简单&…

c#开发IE控件

c#开发IE控件主要是对BHO对象是使用,但是我们知道BHO是一个COM对象,而在.NET下开发基于COM的应用,总觉得不是很简单,这里有受控代码与COM的调用,我查找了下,国内并没有此类信息,下面是译稿,翻译的不好,欢迎指出.介绍:我们在浏览Internet信息的时候,往往需要增强用户浏览信息的,…

JVM直接内存

概述 直接内存并不是虚拟机运行时数据区的一部分&#xff0c;也不是Java 虚拟机规范中农定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类&#xff0c;引入了一种基于通道(Channel)与缓冲区&#xff08;Buffer&#xff09;的I/O 方式&#xff0c;它可以使用native…

英语----专业单词

directive (滴 ‘ruai k tive) n&#xff1a;指令determine 【di tε:min】 (de ter min) v&#xff1a;确定 词根&#xff1a;term 边界 distributions (dis tree biu tion)v&#xff1a;分配 C&#xff1a;发行版 exact (衣 ge za k t) adj&#xff1a;确切的 ex&#xff1a…

js遍历table

js遍历table var tableObj document.getElementById("tableName");var str "";for(var i0;i<tableObj.rows.length;i){for(varj0;j<tableObj.rows[i].cells.length;j){//str tableObj.rows[i].cells[j].innerHTML" ";for(var z0;z<…

深入理解JVM—JVM内存模型

我们知道&#xff0c;计算机CPU和内存的交互是最频繁的&#xff0c;内存是我们的高速缓存区&#xff0c;用户磁盘和CPU的交互&#xff0c;而CPU运转速度越来越快&#xff0c;磁盘远远跟不上CPU的读写速度&#xff0c;才设计了内存&#xff0c;用户缓冲用户IO等待导致CPU的等待成…

Nginx----进阶

用Nginx搭建一个静态的web资源服务器/动静分离 简单使用 1、可以在安装的nginx目录新建自己的目录zy&#xff08;和conf在一个目录下&#xff0c;也就是和html目录在一个目录下&#xff0c;注意如果使用/zy&#xff0c;那么zy目录需要创建在linux根目录&#xff09;&#xff0c…

ASP.NET页面生命周期描述

ASP.NET页面生命周期描述2008-09-12 09:25在以前写个一篇关于ASP.NET页面生命周期的草稿,最近又看了看ASP.NET&#xff0c;做个补充,看看页面初始过程到底是怎么样的 下面是ASP.NET页面初始的过程: 1. Page_Init(); 2. Load ViewState; 3. Load Postback data; 4. Page_Load();…

小程序·云开发的HTTP API调用丨实战

小程序云开发之httpApi调用。 小程序云开发之httpApi调用&#xff08;返回“47001处理”&#xff09; 技术栈 采用 nodejs express 搭建web服务器&#xff0c;采用 axios 请求第三方 httpApi nodejsexpressaxios 项目结构 通过应用生成器工具 express-generator 可以快速创建一…

Java hashCode() 和 equals()使用的场景

第3部分 hashCode() 的作用 hashCode() 的作用是获取哈希码&#xff0c;也称为散列码&#xff1b;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。 hashCode() 定义在JDK的Object.java中&#xff0c;这就意味着Java中的任何类都包含有hashCo…

坚守基本的职业信仰

深陷公司的政治斗争会让任何当事人都疲于奔命&#xff0c;尤其是当这种斗争的双方都是您的上级。除非您一开始就能够知道最终的斗争结果&#xff0c;否则任何具有倾向性的言行都会给自己带来难堪。 深陷入别人的职业斗争是一个职业经理人职业生涯最大的不幸&#xff0c;除非…

Zookeeper----基本原理

Zookeeper作用是什么&#xff1f; 协调分布式系统中的多个服务器&#xff0c;使得系统可以正常工作。 Zookeeper提供了什么&#xff1f; 实际上他只提供了三个东西&#xff0c;一个是文件系统&#xff0c;一个是通知机制&#xff0c;还有一个是集群管理机制 Zookeeper可以做什么…

Java 中 Comparable 和 Comparator 比较

Comparable 简介 Comparable 是排序接口。 若一个类实现了Comparable接口&#xff0c;就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序&#xff0c;假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”&#xff0c;则该List列表(或数组)可以通…

spgridview的过滤功能回调时发生错误~

代码中启用了过滤功能&#xff0c; 但当点击过滤的列时发生错误&#xff1a; error: spgridview_filtercallbackerrorhandler() was called - result 回调时发生错误... 详细见&#xff1a; HTML代码&#xff1a; AllowFiltering"True"FilterDataFields",Name,,…

web---SSL/TSL

对称加密 加密算法秘钥&#xff08;双方持有相同的秘钥&#xff09;&#xff0c;A使用加密算法秘钥加密文件&#xff0c;B使用加密算法秘钥解密文件&#xff1b; 演示一个对称加密RC4算法 注意&#xff1a;RC4加密是有漏洞的 明文和秘钥进行异或得到密文&#xff0c;密文和秘钥…

讨论了好久的问题,IE、Firefox下CSS图片垂直居中的问题

通过百度和谷歌找了好久都没找着一个合适的方法。以下是自己找出的一种方法&#xff0c;自认为还可以&#xff0c;而且&#xff0c;也方便简单。IE:当容器为div,或者tr,只要把容器的Css属性line-height设置成容器的高度就行了.当容器为a,且容器的css属性display为inline-block或…