前言

Java I/O是Java基础之一,在面试中也比较常见,在这里我们尝试通过这篇文章阐述Java I/O的基础概念,帮助大家更好的理解Java I/O。

在刚开始学习Java I/O时,我很迷惑,因为网上绝大多数的文章都是讲解Linux网络I/O模型的,那时我总是搞不明白和Java I/O的关系。后来查了看了好多,才明白Java I/O的原理是以Linux网络I/O模型为基础的,理解了Linux网络I/O模型再学习Java I/O就很方便了,所以这篇文章,我们先来了解I/O的基本概念,再学习Linux网络I/O模型,最后再看Java中的几种I/O。

什么是I/O?

I/O是Input、Output的缩写,即对应计算机中的输入输出,以一次文件读取为例,我们需要将磁盘上的数据读取到用户空间,那么这次数据转移操作其实就是一次I/O操作,更具体的说是一次文件I/O。我们浏览网页,其中在请求一个网页时,服务器通过网络把数据发送给我们,此时程序将数据从TCP缓冲区复制到用户空间,那么这次数据转移操作其实也是一次I/O操作,更具体的说是一次网络I/O。I/O到处都在,十分重要,Java对I/O对底层操作系统的各种I/O模型进行了封装,使我们可以轻松开发。

Linux网络I/O模型

根据UNIX网络编程对I/O模型的分类,UNIX提供了5种I/O模型,分别是:阻塞I/O(Blocking I/O)、非阻塞I/O(Non-Blacking I/O)、I/O多路复用模型(I/O Multiplexing)、信号驱动式I/O(Signal Driven I/O)、异步I/O(Asynchronous I/O)。我们逐步了解一下其基本原理。

阻塞I/O(Blocking I/O)

阻塞I/O是最早最基础的I/O模型,其在读写数据过程中会阻塞。通过下图我们可以看到,当用户进程调用了recvfrom这个系统调用后,内核开始第一阶段的数据准备工作,直到内核等待数据准备完成,然后开始第二阶段的将数据从内核复制到用户空间的工作,最后内核返回结果。整个过程中用户进程都是阻塞的,直到最后返回结果后才接触阻塞block状态。阻塞I/O模型适用于并发量小且对时延不敏感的系统。

非阻塞I/O(Non-Blacking I/O)

当用户进程调用recvfrom这个系统调用后,如果内核尚未准备好数据,此时不再阻塞用户进程,而是立即返回一个EWOULDBLOCK错误。用户进程会不断发起系统调用直到内核中数据被准备好(轮询),此时将执行第二阶段的将数据从内核复制到用户空间的工作,然后内核返回结果。非阻塞I/O模型不断地轮询往往需要耗费大量cpu时间。

I/O多路复用模型(I/O Multiplexing)

I/O多路复用的优点在于单个进程可以同时处理多个网络连接的I/O,其基本原理就是select/epoll函数可以不断的轮询其负责的所有socket,当某个socket有数据到达时,就通知用户进程。

如下图所示,当用户进程调用select函数时,整个进程会被阻塞block住,但是这里的阻塞不是被socket I/O阻塞,而是被select这个函数阻塞。同时内核会监听改select负责的所有socket(这里的socket一般设置为non-blocking),当任何一个socket中的数据准备好时,select就会返回给用户进程,这时候用户进程再此发起一个系统调用,将数据从内核复制到用户空间,并返回结果。

对比I/O多路复用模型和阻塞I/O模型的流程,多路复用多了一个系统调用来完成select环节,除此之外没有太大的不同。Select的优势在于它可以同时处理多个connection,但是会多一个系统调用。多路复用本质上也不是非阻塞的。

信号驱动式I/O(Signal Driven I/O)

首先我们开启socket的信号驱动I/O功能,然后用户进程发起sigaction系统调用给内核后立即返回并可继续处理其他工作。收到sigaction系统调用的内核在将数据准备好后会按照要求产生一个signo信号通知给用户进程。然后用户进程再发起recvfrom系统调用,完成数据从内核到用户空间的复制,并返回最终结果。其基础原理图示如下:

异步I/O(Asynchronous I/O)

用户进程向内核发起系统调用后,就可以开始去做其他事情了。内核收到异步I/O的系统调用后,会直接retrun,所以这里不会对用户进程有阻塞。之后内核等待数据准备完成后会继续将数据从内核拷贝到用户空间(具体动作可以由异步I/O调用定义),然后内核回给用户进程发送一个signal,告诉用户进程I/O操作完成了,整个过程不会导致用户请求进程阻塞。

信号驱动I/O模型是内核通知我们可以发起I/O操作了,而异步I/O模式是内核告诉我们I/O操作已经完成了。

以上就是Linux的5种网络I/O模型,其中前4中都是同步I/O模型,他们真正的I/O操作环节都会将进程阻塞,只有最后一种异步I/O模型是异步I/O操作。

Java中的I/O模型

在JDK1.4之前,基于Java的所有socket通信都是使用阻塞I/O(BIO),JDK1.4提供了了非阻塞I/O(NIO)功能,不过虽然名字叫做NIO,实际底层模型是I/O多路复用,JDK1.7提供了针对异步I/O(AIO)功能。

BIO

BIO简化了上层开发,但是性能瓶颈问题严重,对高并发第时延支持差。

基于消息队列和线程池技术优化的BIO模式虽然可以对高并发支持有一定帮助,但是还是受限于线程池大小和线程池阻塞队列大小的制约,当并发数超过线程池的处理能力时,部分请求法务继续处理,会导致客户端连接超时,影响用户体验。

NIO

NIO弥补了BIO的不足,简单说就是通过selector不断轮询注册在自己上面的channel,如果channel上面有新的连接读写时间时就会被轮询出来,一个selector上面可以注册多个channel,一个线程就可以负责selector的轮询,这样就可以支持成千上万的连接。Selector就是一个轮询器,channel是一个通道,通过它来读取或者写入数据,通道是双向的,可以用于读、写、读和写。Buffer用来和channel交互,数据通过channel进出buffer。

NIO的优点是可以可靠性好以及高并发低时延,但是使用NIO的代码开发较为复杂。

AIO

AIO,或者说叫做NIO2.0,引入了异步channel的概念,提供了异步文件channel和异步socket channel的实现,开发者可以通过Future类来表示异步操作的结果,也可以在执行异步操作时传入一个channels,实现CompletionHandler接口作为回调。AIO不用开发者单独开发独立线程的selector,异步回调操作有JDK地城思安城池负责驱动,开发起来比NIO简单一些,同时保持了高可靠高并发低时延的优点。

java底层模型_Java I/O模型及其底层原理,夯实你的开发基础相关推荐

  1. java委托事件模型_JAVA授权事件模型讲解(原创)

    JAVA的授权事件模型包含三个概念:事件源,事件,事件监听器. 一,事件源:一个产生事件的对象.当这个对象的内部状态改变时,事件就会产生.一个事件源必须注册一个事件监听器已使监听器能够可以接受一个特定 ...

  2. java中reactor模型_Java——Netty Reactor模型(转)

    1. Reactor三种线程模型 1.1. 单线程模型 Reactor单线程模型,指的是所有的IO操作都在同一个NIO线程上面完成,NIO线程的职责如下: 1)作为NIO服务端,接收客户端的TCP连接 ...

  3. java多线程内存模型_Java多线程内存模型

    Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果.在此之前 ...

  4. java线程的内存模型_java多线程内存模型

    java多线程内存模型: 可见性 要实现共享变量的可见性,必须保证两点: 1.线程修改后的共享变量能够及时从工作内存刷新到主内存中: 2.其他线程能够及时把共享变量的最新值从主内存更新到自己的工作内存 ...

  5. java编写太阳_java绘图--太阳系模型

    java绘图在工作中使用的并不是很多,但是从这种小程序中用到很多基本知识和编程理念,最重要的是,可以很快的看到效果,体会到学习java的乐趣,不像C语言那样,学了很久却不知道学了有什么用,在枯燥的学习 ...

  6. java表格模型_java 的表格模型是什么?

    展开全部 DefaultTableModel是常用的java表格模型. 参考代码: package com.dusd; import java.awt.BorderLayout; import jav ...

  7. java 继承 模型_java – 画布形状模型的继承与组合?

    对于以下模型,您更喜欢继承还是组合: >我想在画布上绘制对象,每个对象代表一个数据对象 >将其视为状态机图:椭圆表示状态,线表示它们之间的连接/转换.对象表示本身永远不会改变,即状态将始终 ...

  8. java高并发抢单编程模型_Java高并发模型

    package MainFixedFuc; import java.util.concurrent.ExecutorService; import java.util.concurrent.Execu ...

  9. java堆内存_java堆内存模型

    广泛地说,JVM堆内存被分为两部分--年轻代(Young Generation)和老年代(Old Generation). 年轻代 年轻代是所有新对象产生的地方.当年轻代内存空间被用完时,就会触发垃圾 ...

最新文章

  1. 华人小哥用苹果音箱「隔空」测心律,论文登上Nature子刊
  2. Unity应用架构设计(11)——一个网络层的构建
  3. 目前计算机硬件安全,计算机硬件策划安全问题若干研究论述.doc
  4. 慎用window.showModalDialog()
  5. 那些查了无数遍的问题
  6. TensorFlow神经网络(九)VGG net论文阅读笔记
  7. [CATARC_2017] 第八周
  8. Nginx 静态页面POST 请求提示405 Not Allowed
  9. internet与Internet的区别
  10. Oracle join连接的使用
  11. STM32——DAC数模转换实验
  12. cmd 新增dns_win10在cmd中修改dns方法教程
  13. 2019中国信息安全自主可控行业政策盘点及网络安全行业分析
  14. us域名,什么是us域名?
  15. 蓝牙解码格式哪个最好_让有源音箱飞起来,让汽车音响硬起来,飞傲BTR5蓝牙HiFi解码品评...
  16. 如何在浏览器中运行Linux程序,在linux自定义协议,让浏览器可以调用本地程序...
  17. 小明的游戏(博弈论)
  18. cmd中cd命令使用
  19. 【Shell系列】$(shell pwd)和$(pwd)用法区别
  20. 择校秘籍|保研去 北大软微 还是 上交计算机?

热门文章

  1. 管理大型共享数据库,做到这几点不再头疼!
  2. 华为回应申请大量“鸿蒙”商标;5G第一个演进版本标准正式完成;SUSE 收购 Rancher Labs| 极客头条
  3. 23 岁创业,28 岁成为福布斯亚洲青年领袖,这个“刷脸的男人”有点牛
  4. 苹果的廉价机,你也认为“真香”吗?
  5. 想从远程办公进入 toB 蓝海?它可以,你未必
  6. 代码视角深入浅出理解 DevOps | 原力计划
  7. AI+大数据顶级技术盛会倒计时10天,6.6折票限时特惠!
  8. Google Chrome 正在走 Windows 的老路
  9. 大数据“重磅炸弹”:实时计算框架 Flink
  10. 腾讯、阿里能像 Facebook 一样发币吗?