NIO复习01

NIO 概述:

1. Java NIO 由以下几个核心部分组成:Channels Buffers Selectors

2. 主要Channel的实现:FileChannel DatagramChannel SocketChannel ServerSocketChannel

3. 关键的Buffer实现:ByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer

4. Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便

channel:

1. Java NIO的通道类似流,但又有些不同:既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。通道可以异步地读写。通道中的数据总是要先读到一个Buffer,

或者总是要从一个Buffer中写入

2. FileChannel 从文件中读写数据。

DatagramChannel 能通过UDP读写网络中的数据。

SocketChannel 能通过TCP读写网络中的数据。

ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

Buffer:

1. Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。

2. 使用Buffer读写数据一般遵循以下四个步骤:

1).写入数据到Buffer

2).调用flip()方法

3).从Buffer中读取数据

4).调用clear()方法或者compact()方法

3. 当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数据。

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用clear()或compact()方法。clear()方法会清空整个缓冲区。compact()方法只会清除

已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。

4. 三个属性:

capacity : 作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.

position : 当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。

position最大可为capacity – 1.当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,

position向前移动到下一个可读的位置。

limit : 在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。当切换Buffer到读模式时, limit表示你最多能读到多少数据。

position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。

5. Buffer的分配 : allocate , ByteBuffer buf = ByteBuffer.allocate(48);

6. 向Buffer中写数据,两种方式:

从Channel写到Buffer的例子:int bytesRead = inChannel.read(buf); //read into buffer.

通过put方法写Buffer的例子:buf.put(127);put方法有很多版本,允许你以不同的方式把数据写入到Buffer中

7. flip()方法:flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。

8. 从Buffer中读取数据:

从Buffer读取数据到Channel的例子:int bytesWritten = inChannel.write(buf);

使用get()方法从Buffer中读取数据的例子:byte aByte = buf.get();get方法有很多版本,允许你以不同的方式从Buffer中读取数据。

9. rewind()方法:Buffer.rewind()将position设回0,所以你可以重读Buffer中的所有数据。limit保持不变,仍然表示能从Buffer中读取多少个元素(byte、char等)。

10. clear()与compact()方法:让Buffer准备好再次被写入。可以通过clear()或compact()方法来完成。

如果调用的是clear()方法,position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往

Buffer里写数据。如果Buffer中有一些未读的数据,调用clear()方法,数据将“被遗忘”,意味着不再有任何标记会告诉你哪些数据被读过,哪些还没有。但依旧可以读取出来。

如果Buffer中仍有未读的数据,且后续还需要这些数据,但是此时想要先先写些数据,那么使用compact()方法。

compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,

但是不会覆盖未读的数据。
11. mark()与reset()方法:通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。

12. equals只是比较Buffer的一部分,不是每一个在它里面的元素都比较。实际上,它只比较Buffer中的剩余元素。

有相同的类型(byte、char、int等)。Buffer中剩余的byte、char等的个数相等。Buffer中所有剩余的byte、char等都相同。

13. compareTo()方法:compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:

第一个不相等的元素小于另一个Buffer中对应的元素 。所有元素都相等,但第一个Buffer比另一个先耗尽(第一个Buffer的元素个数比另一个少)。

Scatter/Gather

1. scatter / gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,你可能会将消息体和消息头分散到不同的buffer中,这样你可以方便的处理

消息头和消息体

2. 分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。

实例代码如下:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body };
channel.read(bufferArray);

注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,

channel紧接着向另一个buffer中写。

3. 聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。

实例代码:

ByteBuffer header = ByteBuffer.allocate(128);ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body }; //write data into buffers
channel.write(bufferArray);

buffers数组是write()方法的入参,write()方法会按照buffer在数组中的顺序,将数据写入到channel,注意只有position和limit之间的数据才会被写入。因此,如果一个buffer的容量

为128byte,但是仅仅包含58byte的数据,那么这58byte的数据将被写入到channel中。因此与Scattering Reads相反,Gathering Writes能较好的处理动态消息。

通道之间的数据传输

1. 在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel传输到另外一个channel。

2. transferFrom()

FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中。下面是一个简单的例子:

    RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");

    FileChannel fromChannel = fromFile.getChannel();

    RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");

    FileChannel toChannel = toFile.getChannel();

    long position = 0;

    long count = fromChannel.size();

    toChannel.transferFrom(position, count, fromChannel);

方法的输入参数position表示从position处开始向目标文件写入数据,count表示最多传输的字节数。如果源通道的剩余空间小于 count 个字节,则所传输的字节数要小于请求的字节数。

此外要注意,在SoketChannel的实现中,SocketChannel只会传输此刻准备好的数据(可能不足count字节)。因此,SocketChannel可能不会将请求的所有数据(count个字节)全部传输

到FileChannel中。

3. transferTo()

transferTo()方法将数据从FileChannel传输到其他的channel中。下面是一个简单的例子:

    RandomAccessFile fromFile = new RandomAccessFile("fromFile.txt", "rw");

    FileChannel fromChannel = fromFile.getChannel();

    RandomAccessFile toFile = new RandomAccessFile("toFile.txt", "rw");

    FileChannel toChannel = toFile.getChannel();

    long position = 0;

    long count = fromChannel.size();

    fromChannel.transferTo(position, count, toChannel);

上面所说的关于SocketChannel的问题在transferTo()方法中同样存在。SocketChannel会一直传输数据直到目标buffer被填满。

时间: 2024-07-29 04:27:13

NIO复习01的相关文章

.Net学习笔记----2015-07-15(C#基础复习01)

一个多月的学习,基础部分基本告一段落,现开始基础部分的加强复习 1.注释 单行注释 //注释单行代码 多行注释  /*注释的内容*/ 文档注释   ///注释类和方法 HTML<!--注释的内容--> 2.命名规范 1).Camel  骆驼命名规范:首单词的首字母小写,其余单词首字母大写,变量.字段 int age    string name   char  gender...   string  hightSchool int _chinese (字段前面一定要加下划线) 2).Pasca

T-SQL2012复习-01基本概念

作为一名程序员,对于SQL的使用算是基础中的基础,虽然也写了很多年的SQL,但常常还是记不清一些常见的命令,故而通过一篇博文巩固相关的记忆,并把T-SQL本身的一些新特性再进行一次学习. 首先回顾基础的概念,这部分可以跳过哈,比较枯燥.结构化查询语言SQL是基于集合理论和谓词逻辑的,大学课程中数字逻辑和离散数学主要会涉及这部分的内容. 集合理论是数学家Georg Cantor创建,是基于关系模型的数学分支.集合的定义为,任意集合体是我们感知或者想到的,能够确定的.互异对象m的整体. 谓词逻辑的渊

NIO复习03

SocketChannel: 1. Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道.可以通过以下2种方式创建SocketChannel: 打开一个SocketChannel并连接到互联网上的某台服务器. 一个新连接到达ServerSocketChannel时,会创建一个SocketChannel. 2. 打开 SocketChannel(发送端channel?): SocketChannel socketChannel = SocketChannel.open(

JAVA NIO复习笔记

1. JAVA NIO是什么? 从JDK1.4开始,java提供了一系列改进的输入/输出处理的新功能,这些功能被统称为新IO(New IO,简称NIO),新增了许多用于处理输入/输出的类,这些类都被放在java.nio包以及子包下, 并且对原java.io包中的许多类都以NIO为基础进行了改写. 2. 为什么使用JAVA NIO? NIO和传统的IO有相同的目的,都是用于进行输入/输出,但新IO采用内存映射文件的方式来处理输入/输出,新IO将文件或文件的一段区域映射到内存中,这样就可以像访问内存

NIO入门-----01

package com.sico.pck01_nio; import java.nio.ByteBuffer; import org.junit.Test; /** * @author Sico * 1.NIO入门:三个核心概念如下: *   |--通道:连接作用,连接数据源和目标地 *   |--缓冲区:用于存取数据 *   |--选择器: * * 2.NIO与IO的区别: *   |--IO面向流,NIO面向缓冲区 *   |--IO阻塞,NIO非阻塞 *   |-- * 3.(1)缓冲区:

NIO复习(2):channel

上篇学习了NIO的buffer,继续来学习channel,类图如下(注:为了不让图看起来太复杂,隐藏了一些中间的接口) Channel派生了很多子接口,其中最常用的有FileChannel(用于文件操作)以及SocketChannel.ServerSocketChannel(用于网络通讯),下面用几段示例代码学习其基本用法: 一.文件写入 1.1 入门示例 public static void fileWriteReadSimpleDemo() throws IOException { Stri

C#基础总复习01

马上就快毕业了,准备把这几个月所学到的知识梳理一下,这儿所写的都是一些C#中最基础的东西(大牛不要笑话我,这也是我记录的一些笔记等等),希望能帮到一些正在学习这方面的知识的人,如果有写的不对的地方,望大神们指点. 先从最基础的说起: 1:c#是强类型语言:区分大小写:对变量的类型必须有一个明确的定义. 2:赋值运算符“=”:等号在c#并不是相等的意思,而是表示赋值,把等号右边的值赋值给等号左边的变量,由等号连接的表达式,叫做赋值表达式.要求等号两边的数据类型必须一致. 3:加号的使用:①连接,当

HTML+CSS专项复习01

1.onchange是表单内容改变时触发事件: onaclive事件是页面打开了,第二次或两次以上页面激活显示时触发: onload事件是页面第一次打开的时候触发,表示页面加载完执行的事件: onresize事件会在窗口或框架被调整大小时发生(BOM对象): 2.定义和用法 <hr> 标签在 HTML 页面中创建一条水平线. 水平分隔线(horizontal rule)可以在视觉上将文档分隔成各个部分. 定义和用法 <br> 可插入一个简单的换行符. <br> 标签是空

数据库复习01

1.select * from tableName;– 使用通配符的优点:书写方便.可以检索未知列– 使用通配符的缺点:降低检索的性能 --------------------------------------------------------------------------------2.select distinct empno from emp;distinct必须放在开头• 多字段– 每个字段都一样才去重 3.select ename||'的年薪为:'||sal*12 from