Java IO、NIO、AIO知识总结
本文主要讲述下自己对IO的理解,对IO的用法和细则可能没有顾虑到。
本文的理解基于以下几篇文章,他们对各自部分都讲的很细,对我理解IO提供了很大帮助。
https://www.cnblogs.com/ylspace/p/8128112.html
该文主要讲解了Java IO的类体系以及他们各自的用处。
https://www.jianshu.com/p/03852a291c56
https://blog.csdn.net/fcbayernmunchen/article/details/8635427#commentBox
https://blog.csdn.net/cringkong/article/details/80274148
这些文章讲解了有关Java Buffer的原理,包括allocate、allocateDirect、map等不同IO方式他们的底层知识。
https://blog.yoodb.com/yoodb/article/detail/1498
该文章浅谈了NIO、AIO的知识。
正文
首先是我整理的思维导图

IO的理解
要理解Java IO设计得先了解系统IO,系统不允许程序直接访问硬盘,而是先将用户所需数据准备在系统缓冲区中再转移到用户内存,所以系统IO操作经过三个地方,1、硬盘 2、系统缓冲 3、用户进程空间。File就像是对硬盘的抽象,而stream/reader/writer就是对系统缓冲的抽象,而我们用的Buffer就是用户进程空间的抽象。
IO的体系结构也是很直观的,对应字节处理和字符处理有了字节流inputstream、outputsream及字符流reader、writer。其中inputsream和reader对应输入流,outputsream、writer对应输出流。
根据接受或写出通道的不同,每个IO流类下衍生出了很多细分类用于处理不同通道。数据来源可以有如下:file、char[]、byte[]、网络流等。
装饰者模式
在IO类中有一些类叫FilterXX及它的子类即是装饰者,比如我们常用的BufferInputSream和BufferOutStream,它可以自动帮我们建立并管理线程中的buffer。
那么什么是装饰者模式呢?

首先搞清楚装饰者的目的是:动态、透明地将责任附加到对象上,若要扩展功能,装饰者提供比继承更有弹性的替代方案。为了跟装饰前看起来一样,它和被装饰者共同装配了的同个接口,为了透明增加功能,它持有了被装配对象(其实是接口),它的方法包括了装饰功能和唤醒被装饰者的方法。
Why Decorator?
装饰者的目的是对类进行拓展,这跟继承的目标相似。他们特点是什么呢?
l 动态性 装饰者对象可以在程序运行阶段根据需求动态的拓展功能,那个类需要拓展功能只要将相应装饰类组合进去。而继承则需要编译阶段就准备好所有可能性将各种组合可能性编译好进行选择。这会造成类冗杂。
l 解耦性 如果是集成需要层层继承,而上层类的功能改变势必会影响下级类的功能。装饰者则不会。
l 装饰者(和继承)可以在被装饰者的行为上扩展行为,也可以完全替代被装饰者的行为.
l 装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂。
l 当只能获取类对象没有class文件时只能用装饰者模式进行加强。
NIO的理解
NIO是一种非阻塞式的IO,要理解它我们得先解决几个概念。
系统IO阶段: 1、数据准备阶段(系统从磁盘读取) 2、将系统缓冲数据转移到用户本地内存阶段。
什么是阻塞?非阻塞?
答:阻塞非阻塞注重的是数据准备阶段线程有没有造成线程等待,如果数据准备阶段线程需一直等待则是阻塞的,否则是非阻塞。
什么是同步?异步?
答:同步异步注重的是整个IO过程有没有造成IO等待,一些非阻塞IO虽然系统准备阶段没有造成等待,但将数据从内核缓冲区转移到用户内存里还是需要等待。
五种IO模型
由于篇幅有限,不重点讲IO模型,观点基于《UNIIX网络编程卷1:套接字联网API》 第六章。
同步阻塞IO:会造成整个IO过程等待。
同步非阻塞IO:系统准备数据阶段不会造成等待。
信号式IO:系统准备阶段不会造成等待,并且系统准备完成会发送信号给线程。
IO复用:由一个线程管理多个IO,底层调用时select和epoll(select需论询,epoll信号驱动),多个IO只要有一个准备好就线程就不会被阻塞,有效减少了系统准备阶段等待时间。
异步IO:整个IO无需等待。完成时返回成功指示。
回到我们整体NIO,很明显NIO借用的是IO复用的思想。NIO常使用的三个类即是Selector、Buffer、Channel 。使用的方式就是将Channel注册到selector内,轮询到那个IO可用就在Channel和Buffer间进行读写信息。
Selector有三种选择方法:select()、select(long timeout)、selectNow();前两种是阻塞式的,如果一个都没准备好还是会被阻塞,selectNow()是非阻塞式的,它能立即返回是否准备好的信号。
同样继承AbstractSelectableChannel也可以通过设置configureBlocking(false)达到非阻塞的目的。我有一个疑问就是selectNow()+非阻塞Channel是否已经达到异步了呢?因为任何一个过程都没造成等待。当然具体以后再细究,因为Channel 是native代码。。。。
NIO中的Buffer分配方式,ByteBuffer.allocate()、ByteBuffer().allocateDirect()以及MappedByteBuffer、TransrferTo()
普通IO方式是通过ByteBuffer.allocate(),在 Java堆上分配内存,因此系统IO过程是:硬盘→系统缓冲→用户内存空间→系统缓冲→硬盘。
而ByteBuffer().allocateDirect()则是在native堆上分配内存,减少了native堆到Java堆中的复制,加快了速度,但也失去了Java GC的便利性。
MappedByteBuffer:直接建立用户空间与硬盘间的映射,IO过程省略了数据复制到系统内核缓冲的步骤。这里有个问题是为什么需要系统内核缓冲?因为我们IO时往往会继续读取局部上下文,系统为了提高IO效率,直接在内核建立缓冲区缓冲IO数据的上下文以便接下来使用,但如果我们要IO大文件,文件大小超过系统缓冲,这样缓冲区显然是无意义的,因此有了这种方法来解决大文件的IO。
TransferTO() 它是以上方法的包装,如果传递对象是FileChannel,则使用MappedByteBuffer的方式,如果是其他channel则使用allocateDirect()方式。
AIO
AIO是完全的异步IO,它实现的核心是异步通道AsynchronizedXXChannel和获取异步结果的接口Future。
异步通道进行读写时会另开一个线程进行IO操作,操作完成它会将改变接受结果类的完成信号并且将结果赋予到接收结果类(Future)上,我们需要结果时,通过访问接收类信号量,是则获取结果。
Java IO、NIO、AIO知识总结的更多相关文章
- 一文理解Java IO/NIO/AIO
目录 概述 一.IO流(同步.阻塞) 二.NIO(同步.非阻塞) 三.NIO2(异步.非阻塞) 正文 概述 在我们学习Java的IO流之前,我们都要了解几个关键词 同步与异步(synchronou ...
- IO NIO AIO及常用框架概述
概述 nio 同步: 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步: 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需 ...
- 3. 彤哥说netty系列之Java BIO NIO AIO进化史
你好,我是彤哥,本篇是netty系列的第三篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们介绍了IO的五种模型,实际上Java只支持其中的三种,即BIO/NIO/ ...
- java IO NIO BIO 最权威的总结
1. BIO (Blocking I/O) 1.1 传统 BIO 1.2 伪异步 IO 1.3 代码示例 1.4 总结 2. NIO (New I/O) 2.1 NIO 简介 2.2 NIO的特性/N ...
- JAVA bio nio aio
[转自]http://qindongliang.iteye.com/blog/2018539 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? ...
- java BIO/NIO/AIO 学习
一.了解Unix网络编程5种I/O模型 1.1.阻塞式I/O模型 阻塞I/O(blocking I/O)模型,进程调用recvfrom,其系统调用直到数据报到达且被拷贝到应用进程的缓冲区中或者发生错误 ...
- Java IO/NIO教程
Java IO教程 http://tutorials.jenkov.com/java-io/index.html Java NIO教程 英文版: http://tutorials.jenkov.com ...
- Java IO NIO详细讲解
1.IO Java IO概述 2.NIO Java NIO浅析
- JAVA的 IO NIO AIO笔记
IO linux内核将所有外部设备都看做一个文件来操作,对一个文件的读写会调用内核系统命令,放回一个file descriptor(文件描述符), 对一个socket的读写也会有相应 ...
- Java之io nio aio 的区别
这个问题最近面试总是遇到,作为一个只会写流水代码的程序员,一脸懵逼.看了网上的解释,看的还是很模糊,说下我对这个的理解. 先引出一个话题,两个大水缸,一个空一个满,让你把一个缸里面的水弄到另一个里面. ...
随机推荐
- Freescale MKL16Z1288VF4 芯片调试接口
WDOG监视内部系统操作,并在发生故障时强制复位.它可以运行在一个独立的1 kHz低功率振荡器,具有可编程刷新窗口,以检测程序流或系统频率的偏差. 看门狗计时器保持一个时间在系统上运行,并重置它,以防 ...
- SpringBoot与SpringCloud的版本对应详细版
大版本对应: Spring Boot Spring Cloud 1.2.x Angel版本 1.3.x Brixton版本 1.4.x stripes Camden版本 1.5.x Dalston版本 ...
- Linux系统编程——Daemon进程
目录 Daemon进程介绍 前提知识 Daemon进程的编程规则 Daemon进程介绍 Daemon运行在后台也称作"后台服务进程". 它是没有控制终端与之相连的进程.它独立与控制 ...
- Unity Input,生命周期,Light,获取组件
1. 递归方法遍历获取指定子物体 知识点:递归的使用:transform.childCount.GetChild(index) 2. Input输入控制类,检测玩家输入 知识点: Input ...
- 5、分布式缓存Redis之bitmap、setbit
基本语法: 1)SETBIT redis 127.0.0.1:6379> setbit KEY_NAME OFFSET VALUE //该命令用于对 key 所储存的字符串值,设置或清除指定偏移 ...
- 转载 修改oracle用户密码永不过期
1.查看用户的proifle是哪个,一般是default: sql>SELECT username,PROFILE FROM dba_users; 2.查看指定概要文件(如default)的密码 ...
- c语言函数参数类似继承的传递
函数的参数如果是一个父结构的指针, 这个结构包含在另一个子结构中, typedef struct test_node_one test_node_one_t; typedef struct test_ ...
- 如何实现 C/C++ 与 Python 的通信?
属于混合编程的问题.较全面的介绍一下,不仅限于题主提出的问题.以下讨论中,Python指它的标准实现,即CPython(虽然不是很严格) 本文分4个部分 1. C/C++ 调用 Python (基础篇 ...
- chown nagios:nagios -R /var/lib/php/
chown nagios:nagios -R /var/lib/php/
- log4j2 Filter用法详解
主要说下组合过滤器 CompositeFilter ,比较常用 <Filters> 是组合过滤器额标签,它包含的子标签是具体的过滤器,这三个具体过滤器分别是日志等级过滤器,正则表达式过滤器 ...