Unix中的I/O模型和Java NIO

Unix网络编程中的五种I/O模型

阻塞式I/0、非阻塞I/O、I/O复用、信号驱动式I/O、异步I/O

以一个网络输入为例,一个输入操作通常包括两个不同的阶段:

等待数据准备好,将数据从内核拷贝到进程中。具体过程参考下面的图。

阻塞式I/O

默认情况下的I/O模型都是阻塞式I/O,应用进程从调用recvfrom开始到它返回的整个时间段内都是被阻塞的。此也就是说,应用程序进程投入睡眠,内核在检查到有数据准备好之后,将数据从内核复制到进程后才返回。

非阻塞I/O

将套接字设置为非阻塞会通知内核:当所请求的I/O操作要把本进程投入睡眠才能完成时,不要投入睡眠,而是返回一个错误。如图,当用户进程读取数据时而内核没有可读数据时,用户进程并没有阻塞,而是立刻返回EWOULDBLOCK,这样通过轮询返回值,当没有数据准备好,就继续调用recvfrom,当内核准备好了数据,并且再次收到请求数据的系统调用时,就会将数据复制到进程。

I/O复用

阻塞在select或者poll这两个系统调用中的某一个之上,而不是阻塞在真正的I/O系统调用之上。

从图中可以看出,用户进程阻塞在select之上,等到有可读的套接字,就可以调用recvfrom将数据复制到进程缓冲区。

和阻塞式比较起来,I/O复用并没有什么优势,相反还优劣势,因为涉及到两次系统调用,然而使用select的优势在于可以单线程管理多个套接字(描述符)连接。

传统的监控多个socket的解决方案是为每个socket创建一个线程,并使得线程可以再read调用中阻塞,直到数据可用。这事实上将每个被阻塞的线程当作了socket监控器,并将Java 虚拟机的线程调度当作了通知机制。这两者本来都不是为了这种目的而设计的。程序员和Java
虚拟机都为管理所有这些线程的复杂性和性能损耗付出了代价,这在线程数量的增长失控时表现得更为突出。由于开启多个会造成资源的大量浪费。由于网络延迟的原因,同时在处理socket的用户线程往往比实际的socket数量要少很多,然而由于线程数量太多,cpu来回切换却要花费过多的资源。

Java 1.4中首次加入NIO,就是一种I/O复用,使用的selector选择器。

信号驱动式I/O

使用信号,让内核在socket就绪时发送SIGIO信号通知我们。开启套接字的信号驱动式I/O功能。并通过sigaction系统调用安装一个信号处理函数(回调函数),该系统调用立刻返回。随后就可以在信号处理函数中调用recvfrom读取到数据。

异步I/O

当用户进程调用read内核即使没有数据准备好也会立刻返回,并不会阻塞用户进程,然后内核在整个操作完成后再通知进程,通过回调函数通知。这里的整个操作包括等待数据准备好和将数据从内核复制到用户进程的缓冲区。

和信号驱动式I/O的区别是:号驱动式I/O告诉我们什么时候可以启动一个I/O操作,而异步I/O中内核通知我们I/O操作何时完成,就是说等待数据准备好和将数据复制到进程都是内核做的,直到这两步完成后直接通知用户进程拿数据。

Java在jdk1.7中加入了异步I/O叫做AIO

五种I/O模型的区别

阻塞和非阻塞

阻塞和非阻塞的区别在有没有I/O调用所导致的由于数据未准备好造成的进程睡眠。如果一个I/O操作的系统调用发出后,需要让当前进程睡眠,就是阻塞式的,否则就是非阻塞式的。

同步和异步

同步I/O:导致请求进程阻塞直到I/O操作完成,也就是说在数据从内核复制到进程完成之前,进程一直阻塞。

异步I/O:不导致请求进程阻塞。

这样看来,前四种都属于同步I/O,异步就是异步,没有阻塞和非阻塞的概念。

Java中的I/O模型

Bio:阻塞式I/O

Nio:非阻塞I/O(jdk 1.4)

Aio:异步I/O(jdk 1.7)

NIO是什么?

Java在1.4中首次增加了NIO(New I/O,Non-blockingI/O),是一种同步非阻塞的I/O模型。引入NIO的目的在于提高速度,在此基础上,以前版本中旧的I/O操作的函数全部改写为使用NIO时实现,因此即使不显式的使用NIO编写代码,也能从中受益,速度的提高包括文件I/O和网络I/O,网络I/O中最大的收益在于可以使用单线程来管理多个Socket连接,是一种I/O复用。

为什么?

JVM自身在I/O 方面效率欠佳。操作系统与Java基于流的I/O模型有些不匹配。操作系统要移动的是大块数据(缓冲区),这往往是在硬件直接存储器存取(DMA)的协助下完成的。而JVM的I/O 类喜欢操作小块数据——单个字节、几行文本。结果,操作系统送来整缓冲区的数据,java.io的流数据类再花大量时间把它们拆成小块,往往拷贝一个小块就要往返于几层对象。操作系统喜欢整卡车地运来数据,java.io类则喜欢一铲子一铲子地加工数据。有了NIO,就可以轻松地把一卡车数据备份到您能直接使用的地方(ByteBuffer对象)----
Java Nio O‘Reilly Media

传统流I/O是基于字节的,所有I/O都被视为单个字节的移动;而NIO是基于块的,大家可能猜到了,NIO的性能肯定优于流I/O。没错!其性能的提高 要得益于其使用的结构更接近操作系统执行I/O的方式:通道和缓冲器。我们可以把它想象成一个煤矿,通道是一个包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车。卡车载满煤炭而归,我们再从卡车上获得煤炭。也就是说,我们并没有直接和通道交互;我们只是和缓冲器交互,并把缓冲器派送到通道。通道要么从缓冲器获得数据,要么向缓冲器发送数据----Thinking
in java

注:这是一篇笔记,包括自己的思考总结,所有内容均来自

《Unix网络编程》

《Java Nio》

《Thinking injava》

时间: 2025-01-06 18:21:53

Unix中的I/O模型和Java NIO的相关文章

架构设计:系统间通信(5)——IO通信模型和JAVA实践 下篇

接上篇:<架构设计:系统间通信(4)--IO通信模型和JAVA实践 中篇>,我们继续讲解 异步IO 7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持.重点说明了IO模型是由操作系统提供支持,且这三种IO模型都是同步IO,都是采用的"应用程序不询问我,我绝不会主动通知"的方式. 异步IO则是采用"订阅-通知"模式:即应用程序向操作系统注册IO监听,然后继续做自己

JVM内存结构、Java内存模型和Java对象模型

Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文要讨论的JVM内存结构.Java内存模型和Java对象模型,这就是三个截然不同的概念,但是很多人容易弄混. 首先,这三个概念是完全不同的三个概念.本文主要目的是对这三个概念加以区分以及做简单的介绍.而这每一个知识点都是又都是比较复杂的.以后会单独写文章做详细介绍. Jvm内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过

架构设计:系统间通信(3)——IO通信模型和JAVA实践 上篇

1.全文提要 系统间通信本来是一个很大的概念,我们首先重通信模型开始讲解.在理解了四种通信模型的工作特点和区别后,对于我们后文介绍搭建在其上的各种通信框架,集成思想都是有益的. 目前常用的IO通信模型包括四种(这里说的都是网络IO):阻塞式同步IO.非阻塞式同步IO.多路复用IO.和真正的异步IO.这些IO模式都是要靠操作系统进行支持,应用程序只是提供相应的实现,对操作系统进行调用. 上篇中,首先介绍传统的阻塞式同步IO和非阻塞式同步IO两种IO工作模式,然后使用JAVA进行实现:下篇,对多路复

NLP中word2vec的CBOW模型和Skip-Gram模型

参考:tensorflow_manual_cn.pdf     Page83 例子(数据集): the quick brown fox jumped over the lazy dog. (1)CBOW模型: (2)Skip-Gram模型:

基于JVM原理JMM模型和CPU缓存模型深入理解Java并发编程

许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的Java开发工作中,仅仅了解并发编程的创建.启动.管理和通信等基本知识还是不够的.一方面,如果要开发出高效.安全的并发程序,就必须深入Java内存模型和Java虚拟机的工作原理,从底层了解并发编程的实质:更进一步地,在现今大数据的时代,要开发出高并发.高可用.考可靠的分布式应用及各种中间件,更需要深

Java-杂项-java.nio:java.nio

ylbtech-Java-杂项-java.nio:java.nio java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO) ,为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络. 1.返回顶部 1. 中文名:java非阻塞式IO 外文名:java nio 缓冲区:数据容器 特    性:Channel,Buffer,Selector 简    称:nio 目    的:提供非阻

学习 java netty (一) -- java nio

前言:最近在研究java netty这个网络框架,第一篇先介绍java的nio. java nio在jdk1.4引入,其实也算比较早的了,主要引入非阻塞io和io多路复用.内部基于reactor模式. nio核心: - buffer - channel - selector buffer: 类似网络编程中的缓冲区,有 ByteBuffer 字节 CharBuffer 字符 IntBuffer DoubleBuffer- 常用的有ByteBuffer和CharBuffer java nio buf

Java NIO系列教程(四) Scatter/Gather

原文地址:http://ifeve.com/java-nio-scattergather/ Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作. 分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中.因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中. 聚集(gather)写

Java NIO Scatter/Gather

Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作.分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中.因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中.聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Chann