1. 什么是NIO

NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性:

  • NIO是基于块(Block)的,它以块为基本单位处理数据 (硬盘上存储的单位也是按Block来存储,这样性能上比基于流的方式要好一些)

  • 为所有的原始类型提供(Buffer)缓存支持

  • 增加通道(Channel)对象,作为新的原始 I/O 抽象

  • 支持锁(我们在平时使用时经常能看到会出现一些.lock的文件,这说明有线程正在使用这把锁,当线程释放锁时,会把这个文件删除掉,这样其他线程才能继续拿到这把锁)和内存映射文件的文件访问接口

  • 提供了基于Selector的异步网络I/O

所有的从通道中的读写操作,都要经过Buffer,而通道就是io的抽象,通道的另一端就是操纵的文件。

2. Buffer

Java中Buffer的实现。基本的数据类型都有它对应的Buffer

Buffer的简单使用例子:

public class Test {
public static void main(String[] args) throws Exception { FileInputStream fin = new FileInputStream(new File("d:\\buffer.tmp")); FileChannel fc = fin.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); fc.read(byteBuffer); fc.close(); byteBuffer.flip();//读写转换 } }

总结下使用的步骤是:

1. 得到Channel

2. 申请Buffer

3. 建立Channel和Buffer的读/写关系

4. 关闭

下面的例子是使用NIO来复制文件:

public static void nioCopyFile(String resource, String destination)
throws IOException {
FileInputStream fis = new FileInputStream(resource);
FileOutputStream fos = new FileOutputStream(destination);
FileChannel readChannel = fis.getChannel(); // 读文件通道
FileChannel writeChannel = fos.getChannel(); // 写文件通道
ByteBuffer buffer = ByteBuffer.allocate(1024); // 读入数据缓存
while (true) {
buffer.clear();
int len = readChannel.read(buffer); // 读入数据
if (len == -1) {
break; // 读取完毕
}
buffer.flip();
writeChannel.write(buffer); // 写入文件
}
readChannel.close();
writeChannel.close();
}

Buffer中有3个重要的参数:位置(position)、容量(capactiy)和上限(limit)

这里要区别下容量和上限,比如一个Buffer有10KB,那么10KB就是容量,我将5KB的文件读到Buffer中,那么上限就是5KB。

Buffer中大多数的方法都是去改变这3个参数来达到某些功能的:

public final Buffer rewind()     将position置零,并清除标志位(mark)

public final Buffer clear()        将position置零,同时将limit设置为capacity的大小,并清除了标志mark

public final Buffer flip()           先将limit设置到position所在位置,然后将position置零,并清除标志位mark,通常在读写转换时使用

文件映射到内存

public static void main(String[] args) throws Exception {
RandomAccessFile raf = new RandomAccessFile("C:\\mapfile.txt", "rw");
FileChannel fc = raf.getChannel();
// 将文件映射到内存中
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0,
raf.length());
while (mbb.hasRemaining()) {
System.out.print((char) mbb.get());
}
mbb.put(0, (byte) 98); // 修改文件
raf.close();
}

3. Channel

Channel有点类似于流,一个Channel可以和文件或者网络Socket对应。

selector是一个选择器,它可以选择某一个Channel,然后做些事情。

一个线程可以对应一个selector,而一个selector可以轮询多个Channel,而每个Channel对应了一个Socket。

当selector调用select()时,会查看是否有客户端准备好了数据。当没有数据被准备好时,select()会阻塞。

selectNow()与select()的区别在于,selectNow()是不阻塞的,当没有客户端准备好数据时,selectNow()不会阻塞,将返回0,有客户端准备好数据时,selectNow()返回准备好的客户端的个数。平时都说NIO是非阻塞的,但是如果没有数据被准备好还是会有阻塞现象。

当有数据被准备好时,调用完select()后,会返回一个SelectionKey,SelectionKey表示在某个selector上的某个Channel的数据已经被准备好了。

只有在数据准备好时,这个Channel才会被选择。

这样NIO实现了一个线程来监控多个客户端。

NIO和AIO的区别和总结

nio:

1. NIO会将数据准备好后,再交由应用进行处理,数据的读取/写入过程依然在应用线程中完成,只是将等待的时间剥离到单独的线程中去。

2. 节省数据准备时间(因为Selector可以复用)

aio:

1. 读完了再通知我(内核内存拷贝到工作内存到过程)

2. 不会加快IO,只是在读完后进行通知

3. 使用回调函数,进行业务处理

NIO是同步非阻塞的

AIO是异步非阻塞的

由于NIO的读写过程依然在应用线程里完成,所以对于那些读写过程时间长的,NIO就不太适合。

而AIO的读写过程完成后才被通知,所以AIO能够胜任那些重量级,读写过程长的任务。

java的NIO和AIO的更多相关文章

  1. Java BIO NIO 与 AIO

    回顾 上一章我们介绍了操作系统层面的 IO 模型. 阻塞 IO 模型. 非阻塞 IO 模型. IO 复用模型. 信号驱动 IO 模型(用的不多,知道个概念就行). 异步 IO 模型. 并且介绍了 IO ...

  2. Java之NIO,BIO,AIO

    Hollis知识星球的一些学习笔记,有兴趣的朋友可以微信搜一下 什么是NIO 什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口.它对于任何计算机系统都非常关键,因而所有 ...

  3. Java BIO、NIO、AIO 学习(转)

    转自 http://stevex.blog.51cto.com/4300375/1284437 先来个例子理解一下概念,以银行取款为例: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Ja ...

  4. JAVA bio nio aio

    [转自]http://qindongliang.iteye.com/blog/2018539 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? ...

  5. JAVA中IO技术:BIO、NIO、AIO

    1.同步异步.阻塞非阻塞概念        同步和异步是针对应用程序和内核的交互而言的. 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作 ...

  6. Java IO 之 BIO、NIO、AIO

    1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...

  7. Java提高班(五)深入理解BIO、NIO、AIO

    导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...

  8. Java IO、NIO、AIO知识总结

    本文主要讲述下自己对IO的理解,对IO的用法和细则可能没有顾虑到. 本文的理解基于以下几篇文章,他们对各自部分都讲的很细,对我理解IO提供了很大帮助. https://www.cnblogs.com/ ...

  9. Java的BIO,NIO和AIO的区别于演进

    作者:公众号:我是攻城师 前言 Java里面的IO模型种类较多,主要包括BIO,NIO和AIO,每个IO模型都有不一样的地方,那么这些IO模型是如何演变呢,底层的原理又是怎样的呢? 本文我们就来聊聊. ...

随机推荐

  1. linux的客户端安装步骤配置

    现有一个***.tar.gz的客户端软件,现在客户端安装步骤如下 说明:此软件是一个网络客户端认证软件,因为采用虚拟机中的linux主机,所以此主机的网路配置从只能使用Bridge模式,而不能使用NA ...

  2. DDA_为微分绘制直线算法

    DDA_为微分绘制直线算法 以步进坐标轴部长=1像素为单位,计算y=kx + b,绘制像素点(x, round(y)). 即步进坐标增长1, 另一坐标增长K或者1/k. 程序如下: //数值微分算法D ...

  3. 从hbase到hive,以及sqoop转到mysql解析

    https://blog.csdn.net/qq_33689414/article/details/80328665 hive关联hbase的配置文件 hive和hbase同步https://cwik ...

  4. hdu1302 The Snail

    题目 题目大意: 一只蜗牛在H英尺高的底部,想爬到顶端.蜗牛可以在太阳升起的时候爬上U英尺,但是在晚上睡觉的时候会滑下D英尺.蜗牛的疲劳系数为F(百分比),                       ...

  5. nodejs 上传文件 upload

    只是现在主要用nodejs做后端了,所以记录一些上传文件的使用方法. 上传文件的主要方式: 1.form上传,优点是方便,缺点是没法回调,上传后返回的数据没法处理 2.ajax上传,优点是可控制,有回 ...

  6. Android-JVM中的多线程&垃圾回收

    Java语言是为数不多支持多线程技术的编程语言,而这多线程就不得不提到JVM虚拟机 先看代码案例:(JVM收垃圾) package android.java.thread; class Demo { ...

  7. Python学习-21.Python的代码注释

    在Python中有两种注释,一种是普通注释,另一种是文档注释. 普通注释是使用#开头 print('output something') # here is comment 而Python中多行注释也 ...

  8. docker 多阶段构建

    构建镜像最具挑战性的一点是使镜像大小尽可能的小.Dockerfile中的每条指令都为图像添加了一个图层,您需要记住在移动到下一层之前清理任何不需要的工件.对于多阶段构建,您可以在Dockerfile中 ...

  9. C#如何关闭指定进程

    public static void KillProcess(string strProcessesByName)//关闭线程 { foreach (Process p in Process.GetP ...

  10. silverlight chart 折线图 的线颜色如何修改???

    silverlight  chart 折线图 的线颜色如何修改??? 我做出来都是这些偏黄色,请问如何修改线的颜色,以及线的宽度?谢谢