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;…

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 数据库的服务比较简单&…

深入理解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…

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

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

Zookeeper----基本原理

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

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;密文和秘钥…

Nginx----实现https站点

1、首先给域名设置证书&#xff0c;可以去阿里云购买 1、下载自动化脚本 目的&#xff1a;帮我们自动在nginx配置中添加证书 yum install python2-certbot-nginx2、输入命令 certbot --nginx --nginx-server-root/usr/local/openresty/nginx/conf/ -d zy.com 选择我们的url请求…

TCP/IP四层模型和OSI七层模型的概念

TCP/IP四层模型 TCP/IP是一组协议的代名词&#xff0c;它还包括许多协议&#xff0c;组成了TCP/IP协议簇。TCP/IP协议簇分为四层&#xff0c;IP位于协议簇的第二层(对应OSI的第三层)&#xff0c;TCP位于协议簇的第三层(对应OSI的第四层)。 TCP/IP通讯协议采用了4层的层级结构&…

setsockopt()用法(转载)

1. 如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分&#xff09;调用 closesocket&#xff08;一般不会立即关闭而经历TIME_WAIT的过程&#xff09;后想继续重用该socket&#xff1a; BOOL bReuseaddrTRUE; setsockopt(s,SOL_SOCKET ,…

《深入浅出Google Android》即将隆重上市!

《深入浅出 Google Android 》 作者在线答疑活动开始啦 &#xff1a;http://www.hiapk.com/bbs/forum-41-1.html 随着越来越多的手机 厂商和移动运营商加入了开放手机联盟&#xff0c; Android 平台 越来越受到广大开发 者的关注和推崇。 本书是是国内最早的 And…

公钥基础设施PKI体系介绍

PKI(Pubic Key Infrastructure)是一种遵循标准的利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范。用户可利用PKI平台提供的服务进行安全通信。 使用基于公钥技术系统的用户建立安全通信信任机制的基础是&#xff1a;网上进行的任何需要安全服务的通信都是建…

Flag counter被博客园禁了的解决方法

突然发现Flag counter展示不出来 一开始还以为是网速的问题&#xff0c;后来搜了搜才知道博客园把Flag counter禁了....之前的访问量全没了5555&#xff08;虽然也没多少&#xff09; 只好换一个记录访问量的好了&#xff1a;https://clustrmaps.com/ 进去之后创建账户 把网址贴…

Nginx----高级

Nginx请求流程 Nginx进程结构 Nginx有两种进程结构&#xff0c;一种是单进程&#xff08;可以用于测试&#xff09;&#xff0c;一种是多进程&#xff08;用于生产&#xff0c;默认&#xff09; Nginx会按需同时运行多个进程&#xff1a;一个主进程(master)和几个工作进程(work…

基于Zookeeper的分布式锁

实现分布式锁目前有三种流行方案&#xff0c;分别为基于数据库、Redis、Zookeeper的方案&#xff0c;其中前两种方案网络上有很多资料可以参考&#xff0c;本文不做展开。我们来看下使用Zookeeper如何实现分布式锁。 什么是Zookeeper&#xff1f; Zookeeper&#xff08;业界简…

web----epoll实现原理

epoll可以用单进程单线程实现高并发 首先我们可以实现单进程单线程实现高并发&#xff08;模拟非阻塞IO请求&#xff09; 服务端 //服务端 public class BlockNIOServer {public static void main(String[] args) throws IOException, InterruptedException {//获取通道ServerS…

web----tcp三次握手

1、首先为什么需要握手 首先我们看一下TCP报文段的结构 TCP报文段中的窗口这16位字段部分&#xff0c;这里窗口的作用就是为了实现流量的控制&#xff0c;为什么会有流量的控制的引入&#xff1f;&#xff1f;&#xff1f;它是这样来的&#xff1a;若是发送方发送数据的速度大于…