四川网站设计,查流量网站,运动分类的网站设计论文,wordpress 禁止百度转码NIO共引入了4个概念#xff1a; - 缓存区#xff1a;表示数据存放的容器#xff0c;提供可读写的数据缓存区#xff1b; - 字符集#xff1a;用来对缓存数据进行解码和编码#xff0c;在字节和Unicode字符之间转换#xff1b; - 通道#xff1a;用来接收或发送数据 - 缓存区表示数据存放的容器提供可读写的数据缓存区 - 字符集用来对缓存数据进行解码和编码在字节和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 - 通道Channeljava.nio.channels包中定义了通道API包括文件通道FilechannelSocket通道SocketChannelServerSocket通道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();//在此缓存区的位置设置标记
这些属性总是满足以下条件 0markpositionlimitcapacity 因此标记、位置、限制和容量值遵守以下不变式 0标记位置限制容量 对初始化的Buffer来说position为0limitcapacity。 ②Buffer缓存区的3个数据操作 a、清除clear()把position设为0把limit设为capacity一般在把数据写入Buffer前调用
Buffer clear();//清除此缓存区
b、反转flip():把limit设为当前position把position设为0一般在从Buffer读取出数据前调用
Buffer flip();//反转此缓存区
c、重绕rewind():把position设为0limit不变一般在把数据重新写入Buffer前调用
Buffer rewind();//重绕此缓存
Buffer对象有可能是只读的这时任何对该对象的写操作都会触发一个ReadOnlyBufferException。isReadOnly()方法可以用来判断一个Buffer是否只读。 ③Buffer缓存区的8个实现类 对于每个非boolean基本类型都有一个Buffer子类与之对应这些子类位于包java.nio.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中类和接口的关系 图中最下面的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