Java中IO——NIO
一、引入
当引入一些新功能的时候,那说明之前的设计可能还需要完善。
1、阻塞式
在传统的IO输入输出中,如果我们从流中去读数据,而数据源中没有数据时,程序就会阻塞该线程。阻塞式线程的一种基本状态,可以理解成线程就在那里等着,什么也不做。
显然,这种阻塞式的io如果正常执行还好,一旦数据缺失或网络故障,就没什么优点可言了。
2、效率不高
传统IO的介绍中,我们把流比作水管中的水滴,读和写操作都在操作“水滴”,而且一次只能操作一个“水滴”(字节),效率确实有限。
因此,java4引入了NIO来完善这些地方。
二、重要特性
NIO可以理解成New IO,百科上说是Non-Blocking非阻塞式IO,这个名字就比较直白了。当然,除了非阻塞的优点,他还有别的特性。
内存映射
NIO也是为了解决输入输出的问题,由于传统方法效率不高,NIO采用了内存映射的方式来提高效率。具体通过Channel对象来体现。
Channel通道是模拟的传统IO,可以通过它读取和写入数据。它不同之处在于提供了map()方法,可以直接将一块数据映射到内存。
标准访问:
内存映射:
另外,通道是双向的,而流式单向的。通道可以用于读、写或同时读写。
缓冲支持
传统IO是面向流的,NIO是面向缓冲的。
Buffer是一个数组容器,发送到Channel的对象都必须先放到Buffer中,而从Channel中读取的数据也必须先放到Buffer中。简单的说,Buffer类似Channel对外交互的一个中介,如果Channel的读写都不通过Buffer了,那缓冲也没什么意义了。
Buffer是一个抽象类,子类包括了基本数据类型的对应类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer等。
常用变量:
// Invariants: mark <= position <= limit <= capacity
//可选的标记
private int mark = -1;
//位置
private int position = 0;
//界限
private int limit;
//容量
private int capacity;
//构造函数
// Creates a new buffer with the given mark, position, limit, and capacity,
// after checking invariants.
//
Buffer(int mark, int pos, int lim, int cap) { // package-private
if (cap < 0)
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap;
limit(lim);
position(pos);
if (mark >= 0) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")");
this.mark = mark;
}
}
其中,这几个变量的关系如下所示:
重要方法:
/**
* Flips this buffer. The limit is set to the current position and then
* the position is set to zero. If the mark is defined then it is
* discarded.
*
* <p> After a sequence of channel-read or <i>put</i> operations, invoke
* this method to prepare for a sequence of channel-write or relative
* <i>get</i> operations. For example:
*
*/
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
flip()方法将limit放在position的位置,然后将position的值设为0,mark恢复初始化值-1,可参考上面的图。此时这三个变量都已经恢复初值,Buffer的读写指针回到了开始位置。装入数据结束后调用该方法,为输出数据做好了准备。
/**
* Clears this buffer. The position is set to zero, the limit is set to
* the capacity, and the mark is discarded.
*
*/
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
clear()不是清除数据内容,将容量capacity值赋给了limit。在输出数据结束后,调用clear,为再次向Buffer装入数据做准备。
单线程处理
NIO中使用单个线程来处理多个Channel,这样一来,不会因为线程间的上下文切换付出大量的开销,不需要考虑共享资源的问题。一个线程可以管理多个网络连接。具体的实现是Selector。
Selector选择器的工作原理:首先向Selector中注册Channel,然后Selector就可以检测到一个或多个NIO通道,并且能够了解每个通道是否已经做好准备进行读写。
是不是有点类似观察者模式、监听的赶脚( ⊙ o ⊙ )!
说了这么多,这里也可以通过对比图来学习。
图一:old io
图二:nio
三、小结
本篇博客通过对比新旧IO,来介绍了NIO几大特性。侧重原理的理解,读者可再找些小demo练习一下。
NIO中主要强调的是non-blocking非阻塞io(即非bio),在java7之后推出了NIO.2,增加了异步IO的实现(即aio)。两者结合非阻塞异步io,差不多就完美了。(^o^)/~
Java中IO——NIO的更多相关文章
- JAVA中的NIO (New IO)
简介 标准的IO是基于字节流和字符流进行操作的,而JAVA中的NIO是基于Channel和Buffer进行操作的. 传统IO graph TB; 字节流 --> InputStream; 字节流 ...
- java中的NIO和IO到底是什么区别?20个问题告诉你答案
摘要:NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多. 本文分享自华为云社区<jav ...
- Java中的NIO基础知识
上一篇介绍了五种NIO模型,本篇将介绍Java中的NIO类库,为学习netty做好铺垫 Java NIO 由3个核心组成,分别是Channels,Buffers,Selectors.本文主要介绍着三个 ...
- JAVA中IO总结
JAVA中IO流主要分为两大类: 字节流:InputStream+OutputStream 字符流:Reader+Writer 字节流: InputStream是所有字节输入流的父类 OutputSt ...
- Java中IO流的总结
有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...
- java 中 IO 流分为几种?(未完成)
java 中 IO 流分为几种?(未完成)
- Java中的NIO和IO的对比分析
总的来说,java中的IO和NIO主要有三点区别: IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器(Selectors) 1.面向流与面向缓冲 Java NIO和IO之间第一个最大的 ...
- JAVA中IO技术:BIO、NIO、AIO
1.同步异步.阻塞非阻塞概念 同步和异步是针对应用程序和内核的交互而言的. 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作 ...
- JAVA中IO和NIO的详解分析,内容来自网络和自己总结
用一个例子来阐释: 一辆客车上有10个乘客,他们的目的地各不相同,当没有售票员的时候,司机就需要不断的询问每一站是否有乘客需要下车,需要则停下,不需要则继续开车,这种就是阻塞的方式. 当有售票员的时候 ...
随机推荐
- LeetCode 中级 - 路径总和2(113)
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树,以及目标和 sum = 22, 5 / \ 4 8 ...
- 洛谷P3871 [TJOI2010]中位数(splay)
题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从 ...
- chromium之pickle
pickle谷歌翻译成泡菜 醉了,看一下头文件的说明 // This class provides facilities for basic binary value packing and unpa ...
- Mysql8.0 3306端口无法远程连接
在阿里云上搭建MySql8.0数据库服务,在阿里云上可以成功连接登陆使用,但用自己的电脑远程连接时却无法成功连接 经过资料查找,找出原因如下: 1.首先通过查看MySQL的的用户信息 可以看到host ...
- java 代码调用函数
sql 中调用函数 getDistance(lng1 float, lat1 float, lng2 float, lat2 float) 例如: SELECT id, f_seller_id sel ...
- datatable根据条件设置表格行中字的颜色或背景
使用row回调函数 "rowCallback": function (row, data) { if (xxx) { //给行添加背景色 $(row).css("back ...
- linux系统下病毒排除思路
1.top查看是否有特别吃cpu和内存的进程,病毒进程kill是杀不死的,因为ps命令被修改 2.ls -la /proc/病毒进程pid/ pwd为病毒进程程序目录 一般在/usr/bin下 3. ...
- Axure RP Extension for Chrome安装
Axure RP Extension for Chrome安装 Axure RP Extension for Chrome是一款谷歌插件,主要可以用来查看原型文件.以前安装插件的时候总是找半天资源,很 ...
- Hadoop(25)-高可用集群配置,HDFS-HA和YARN-HA
一. HA概述 1. 所谓HA(High Available),即高可用(7*24小时不中断服务). 2. 实现高可用最关键的策略是消除单点故障.HA严格来说应该分成各个组件的HA机制:HDFS的HA ...
- Hadoop(4)--Hbase
Hadoop 其它组成角色介绍--Hbase 在apache的官方网站上,对于Hbase的定义是他是Hadoop的第一个分布式.可扩展的大数据存储的数据库,他的目标是将非常大的表托管到一个集群中进行相 ...