前言

前面两篇文章(Java NIO之理解I/O模型(一)、Java NIO之理解I/O模型(二))介绍了,IO的机制,以及几种IO模型的内容,还有涉及到的设计模式。这次要写一些更贴近实际一些的内容了,终于要说到了Java中的各种IO了。我也是边学边理解,有写的不对的地方,欢迎小伙伴们指出和补充。

Java中的IO分类

BIO

BIO是指 Blocking IO 在JDK1.0的时候就引入了,直到JDK1.4一直都是Java中唯一的IO方式。它的主要实现方式就是,一个线程执行一个请求,如果请求数据量较大线程就会一直占用着,又或者请求什么也不做,也是会占用一个线程的,这样当客户端请求数量变多时,服务端线程数也跟着变多,最终就会导致服务端CPU崩溃的。当然可以使用线程池来减小CPU的压力,但是毕竟线程池也不是从本质上解决问题(长链接,线程池大小,以及拒绝策略等等因素都要考虑)。

无论是网络连接还是本地读取输出操作都是这种方式。具体的例子我就不举了(毕竟BIO不是本次的重点)。

NIO

Java中的NIO其实就是使用的多路I/O复用模型,前面的文章已经介绍过原理了,但是在理解Java的NIO之前,还是先介绍几个Java NIO的基础概念:Channel(通道),Buffer(缓冲区),Selector(选择器)。

Channel(通道)

Channel可以理解为,互通的管道,和Java的IO中的各种Stream(InputStream、OutputStream等等)一个等级,只不过Channel是双向的,而Stream是单向的。通道的作用是将数据移入或移出道各种I/O源,即可读又可写。

在Java中Channel类的层次结构相当复杂,有多个接口和许多可选操作。不过,常用的也就几个。

FileChannel

DatagramChannel

SocketChannel

ServerSocketChannel

FileChannel可以对文件进行读和写,DatagramChannel可以以UDP的协议来进行数据读写,SocketChannel以TCP的协议来对网络两端进行读写,ServerSocketChanel能够监听客户端发起的TCP连接,并为每个TCP连接创建一个新的SocketChannel来进行数据读写。

Buffer(缓冲区)

Buffer是一个高效的数据容器,在NIO中所有的数据操作都必须经过缓冲区,这点是和BIO不同的,BIO是直接将数据写到Stream对象中的。因为Stream对象的设计是按顺序一个字节一个字节的传送数据。虽然出于性能考虑,也可以传递字节数组,但是基本概念都是一个字节一个字节的传递数据。通道与之不同之处在于,通道会传送缓冲区的数据块,而且通道的基本概念就是按照一个数据块一个数据块的去读和写。所以也可以将缓冲区理解为一个字节数组,专门用来存储以及准备好出入通道的字节。

如下图:

如上图所示,无论是客户端发送和接收数据,还是服务端接收和相应数据,都是从缓冲区中进行数据操作的。

在Java中除了boolean外,所有的基本数据类型都有特定的Buffer子类:

ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer。网络程序几乎只会使用ByteBuffer,但程序偶尔也会使用其他类型来取代ByteBuffer。

除了数据列表外,每个缓冲区都记录了信息的4个关键部分。无论是何种类型,都有相同的方法来获取和设置这些值:

位置(position)

缓冲区中将读取或写入的下一个位置。这个位置从0开始计,最大值等于缓冲区的大小。可以用下面两个方法获取和设置。

public final intposition();public final Buffer position(int newPosition);

容量(capacity)

缓冲区可以保存的最大数目。容量值在创建缓冲区时设置,此后不能改变。

可以用以下方法读取:

public final int capacity();

限度(limit)

缓冲区中可访问数据的末尾位置。只要不改变限度,就无法读/写超过这个位置的数据,即使缓冲区有更大的容量也没有用。限度可以用下面两个放获取和设置。

public final intlimit();public final Buffer limit(int newLimit);

标记(mark)

缓冲区中客户端指定的索引。通过调用mark()可以将标记设置为当前位置。调用reset()可以将当前位置设置为所标识的位置。

public finalBuffer mark() ;public final Buffer reset();

如果将位置设置为低于现有标记,则丢弃这个标记。

与读取InputStream不同,读取缓冲区实际上不会以任何方式改变缓冲区中的数据。只可能向前或向后设置位置,从而可以从缓冲区中某个特定位置开始读取。类似的程序可以调整限度,从而控制将要读取的数据的末尾。只有容量是固定的。

Selector(选择器)

Selector是Java NIO中最重要的一部分,Selector的作用就是用单线程来轮询处理注册的Channel,一旦哪个Channel的数据准备就绪了,就可以进行处理了。

如下图:

使用Selector,要先向Selector中注册Channel, 然后调用它的select()方法,这个方法会一直阻塞到某个注册的Channel中的事件准备就绪。一旦select()方法返回,线程就可以处理这些事件了,比如新的连接进入,数据接收等。

Selector类并没有注册新通道的方法,register()方法是在SelectableChannel类中声明。SelectableChannel类是实现自Channel接口的,它支持将Channel注册到Selector中。

SelectableChannel提供了两个注册Channel的方法:

public abstract SelectionKey register(Selector sel, intops, Object att)throwsClosedChannelException;public final SelectionKey register(Selector sel, intops)throws ClosedChannelException;

第一个参数代表通道要向哪个选择器注册。第二个参数是SelectionKey类中的一个命名常量,标识所注册的操作。

SelectionKey定义了4个命名位常量,用户选择操作类型:

SelectionKey.OP_READ;

SelectionKey.OP_WRITE;

SelectionKey.OP_CONNECT;

SelectionKey.OP_ACCEPT;

当一个通道需要在同一个选择器中关注多个操作,只需要用户位“或”操作符组合这些常量即可。

channel.register(selector,SelectionKey.OP_READ | SelectionKey.OP_WRITE);

第三个参数是可选的,代表键的附件。这个参数通常用户存储链接状态,例如:如果要实现一个Web服务器,可能要附加一个FileInputStream或FileChannel,这个流或通道连接到服务器提供给客户端的本地文件。

例子:

复制文件的读写操作,可以用来举例说明NIO的一个大致过程。

public static void copyFileByNIO(String src,String dst) throwsIOException {//声明源文件和目标文件

RandomAccessFile aFile = new RandomAccessFile(src, "rw");

RandomAccessFile bFile= new RandomAccessFile(dst, "rw");//获得传输通道channel

FileChannel inChannel =aFile.getChannel();

FileChannel outChannel=bFile.getChannel();//获得容器buffer

ByteBuffer buffer= ByteBuffer.allocate(1024);while(true){//判断是否读完文件

int eof =inChannel.read(buffer);if(eof==-1){break;

}//重设一下buffer的position=0,limit=position

buffer.flip();//开始写

outChannel.write(buffer);//写完要重置buffer,重设position=0,limit=capacity

buffer.clear();

}

inChannel.close();

outChannel.close();

aFile.close();

bFile.close();

}

AIO

AIO这次就不介绍了,我后续要单独的拿出一整篇来介绍AIO。

java io类型_Java NIO之Java中的IO分类相关推荐

  1. java注解类型_Java注解类型

    本篇文章帮大家学习java注解类型,包含了Java注解类型使用方法.操作技巧.实例演示和注意事项,有一定的学习价值,大家可以用来参考. 标记注解类型 标记注解类型是没有元素的注解类型,甚至没有默认值. ...

  2. Java与汽车_Java NIO:IO与NIO的区别

    一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...

  3. Java+包裹类型_java中的包裹类型

    包裹类型将一个基本数据类型的数据转换成对象的形式,从而使得它们可以像对象一样参与运算和传递.下表列出了基本数据类型所对应的包裹类型: 基本类型    包裹类型 boolean    Boolean c ...

  4. java记录类型_Java中的记录类型

    java记录类型 于2020年3月发布的JDK 14引入了记录 (预览语言功能),该记录提供了一种紧凑的语法来声明主要用于保存数据的类. 在记录中 ,所有低级,重复且容易出错的代码都类似于构造函数,访 ...

  5. java 判断类型_Java中类型判断的几种方式

    在Java这种强类型语言中类型转换.类型判断是经常遇到的.今天就细数一下Java中类型判断的方法方式.拉勾IT课小编为大家提供java种类型判断方式. instanceof instanceof是Ja ...

  6. nio java是什么_Java NIO 的前生今世 之一 简介

    简介 Java NIO 是由 Java 1.4 引进的异步 IO. Java NIO 由以下几个核心部分组成: Channel Buffer Selector NIO 和 IO 的对比 IO 和 NI ...

  7. java bytebuffer 读写_java nio bytebuffer文件读写问题

    为什么下面的代码从文件中读不出3和2来?importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOExc ...

  8. java 句柄无效_Java开发网 - java.io.IOException: 句柄无效???

    Posted by:aideliwu Posted on:2004-09-01 21:32 我思考le很久,也查看啦代码很久,可还是百思不得其解, 在Freejava中运行的结果还是: java.io ...

  9. java 变量类型_Java 变量类型

    Java 变量类型 在Java语言中,所有的变量在使用前必须声明.声明变量的基本格式如下: type identifier [ = value][, identifier [= value] ...] ...

最新文章

  1. 大容量类 Redis 存储的场景补充-pika
  2. sql 2020 0528
  3. 响应式网格项目动画布局_响应式网格及其实际使用方式:常见的UI布局
  4. tsdb java_OpenTSDB 问题集锦
  5. Auto layout 的使用
  6. vba打开服务器文件,EXCEL+VBA快速部署及运维管理FTP+SMB共享文件服务器
  7. android 图片合成pdf文件,如何在Android上将多个图像合并到PDF文件中 | MOS86
  8. 连接共享打印机0xc00000bcb
  9. vue 文件名乱码_如何解决vue.js中文乱码问题
  10. android随机抽奖代码_Android自定义效果——随机抽奖
  11. 一个简单的acm竞赛题
  12. PostgreSQL 从cmin/cmax到combo cid
  13. 失去后才发现一直都爱
  14. APP(IOS)蒲公英上传成功但下载页报错
  15. CMD快捷指令之磁盘检查(管理员身份运行命令提示符)
  16. 【转载】刘未鹏的C++学习历程 + 小诗一首
  17. ARM64内核内存布局图
  18. 利用Xutils框架进行断点续传下载
  19. java如何创建一个文本框_创建一个有文本框和三个按钮的程序。当按下某个按钮时,使不同的文字(Java..._考试资料网...
  20. [zf from byhh]百度完整的面试经历

热门文章

  1. 安卓颜色标签android
  2. 《计算机小常识》一不小心把windows资源管理器给结束任务了,电脑黑屏了怎么办?
  3. linux之debian自动登录
  4. PCL之点云坐标系空间转换
  5. Qt拖放操作和打印操作
  6. fzyzojP2119 -- 圆圈游戏
  7. 毛发及眼球的渲染技术
  8. php 中 的含义
  9. 什么叫位?什么叫字节?什么叫字长?字长表示了计算机的什么特点?,计算机应用基础...
  10. 用matlab怎么画频率特性,(matlab)频率特性仿真.pdf