描述IO,我们需要从两个层面:

  1. 编程语言
  2. 实现原理
  3. 底层基础

从编程语言层面

BIO | NIO | AIO 以Java的角度,理解,linux c里也有AIO的概念(库),本文只从Java角度入手。

  • BIO,同步阻塞式IO,简单理解:一个连接一个线程
  • NIO,同步非阻塞IO,简单理解:一个请求一个线程
  • AIO,异步非阻塞IO,简单理解:一个有效请求一个线程

BIO

在JDK1.4之前,用Java编写网络请求,都是建立一个ServerSocket,然后,客户端建立Socket时就会询问是否有线程可以处理,如果没有,要么等待,要么被拒绝。即:一个连接,要求Server对应一个处理线程。

NIO

在Java里的由来,在JDK1.4及以后版本中提供了一套API来专门操作非阻塞I/O,我们可以在java.nio包及其子包中找到相关的类和接口。由于这套API是JDK新提供的I/O API,因此,也叫New I/O,这就是包名nio的由来。这套API由三个主要的部分组成:缓冲区(Buffers)、通道(Channels)和非阻塞I/O的核心类组成。在理解NIO的时候,需要区分,说的是New I/O还是非阻塞IO,New I/O是Java的包,NIO是非阻塞IO概念。这里讲的是后面一种。

NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题: 在使用同步I/O的网络应用中,如果要同时处理多个客户端请求,或是在客户端要同时和多个服务器进行通讯,就必须使用多线程来处理。也就是说,将每一个客户端请求分配给一个线程来单独处理。这样做虽然可以达到我们的要求,但同时又会带来另外一个问题。由于每创建一个线程,就要为这个线程分配一定的内存空间(也叫工作存储器),而且操作系统本身也对线程的总数有一定的限制。如果客户端的请求过多,服务端程序可能会因为不堪重负而拒绝客户端的请求,甚至服务器可能会因此而瘫痪。

NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。 
也就是说,这个时候,已经不是一个连接就要对应一个处理线程了,而是有效的请求,对应一个线程,当连接没有数据时,是没有工作线程来处理的。

AIO

与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。 
即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。 
在JDK1.7中,这部分内容被称作NIO.2,主要在java.nio.channels包下增加了下面四个异步通道:

  • AsynchronousSocketChannel
  • AsynchronousServerSocketChannel
  • AsynchronousFileChannel
  • AsynchronousDatagramChannel

其中的read/write方法,会返回一个带回调函数的对象,当执行完读取/写入操作后,直接调用回调函数。


实现原理

说道实现原理,还要从操作系统的IO模型上了解

按照《Unix网络编程》的划分,IO模型可以分为:阻塞IO、非阻塞IO、IO复用、信号驱动IO和异步IO,按照POSIX标准来划分只分为两类:同步IO和异步IO。如何区分呢?首先一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作,同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO、非阻塞IO、IO复用、信号驱动IO都是同步IO,如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO。阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。

收到操作系统的IO模型,又不得不提select/poll/epoll/iocp,关于这四个的理解,不多做解释,自己还没理解到位。

可以理解的说明是:在Linux 2.6以后,java NIO的实现,是通过epoll来实现的,这点可以通过jdk的源代码发现。而AIO,在windows上是通过IOCP实现的,在linux上还是通过epoll来实现的。

这里强调一点:AIO,这是I/O处理模式,而epoll等都是实现AIO的一种编程模型;换句话说,AIO是一种接口标准,各家操作系统可以实现也可以不实现。在不同操作系统上在高并发情况下最好都采用操作系统推荐的方式。Linux上还没有真正实现网络方式的AIO。

底层基础

说到底层,要说Linux系统编程,这里自己也不熟悉,有待后来人补充了。 
只笼统的说一个:AIO实现

在windows上,AIO的实现是通过IOCP来完成的,看JDK的源代码,可以发现

WindowsAsynchronousSocketChannelImpl

看实现接口:

implements Iocp.OverlappedChannel

再看实现方法:里面的read0/write0方法是native方法,调用的jvm底层实现,虚拟机技术不熟悉,不献丑了。

在linux上,AIO的实现是通过epoll来完成的,看JDK源码,可以发现,实现源码是:

UnixAsynchronousSocketChannelImpl

看实现接口:

implements Port.PollableChannel

这是与windows最大的区别,poll的实现,在linux2.6后,默认使用epoll。


最后,几篇解释的不错的文章:

BIO NIO AIO

NIO.2 入门,第 1 部分: 异步通道 API

使用异步 I/O 大大提高应用程序的性能

 

IO模型-java版的更多相关文章

  1. Linux五种IO模型 ——Java学习笔记

    本文摘自网络:     1.阻塞IO(blocking IO) 在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样: 图1 阻塞IO 当用户进程调用了re ...

  2. JAVA版StarDict星际译王简单实现

    由胡正开发的星际译王是Linux平台上很强大的一个开源的翻译软件(也有Windows版本的)支持多种词库.多种语言版本.尤其词库设计比较合理.之前看到一篇博文<星际译王词库应用-自制英汉词典&g ...

  3. 通过实例理解Java网络IO模型

    网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的. 以 ...

  4. 京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    本文节选自<Java面试进阶指北 打造个人的技术竞争力> 面试中经常喜欢问的一个问题,因为通过这个问题,面试官可以顺便了解一下你的操作系统的水平. IO 模型这块确实挺难理解的,需要太多计 ...

  5. JAVA基础知识之网络编程——-网络通信模型(IO模型)

    <Unix网络编程:卷1>中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则.这5中I/O模型分别是: 阻塞式IO 非阻塞式IO I/O复用 信号驱动 ...

  6. 深入理解JAVA I/O系列六:Linux中的IO模型

    IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大致描述了数据从外部磁盘向运行中程序的内存中移动的过程. 用户空间.内核空间 现在操作系统都是采用虚拟存储器, ...

  7. 深入理解JAVA I/O系列六:Linux中的IO模型(转载的文章非常值得学习)

    From:http://www.cnblogs.com/dongguacai/p/5770287.html IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大 ...

  8. Java 网络 IO 模型

    在进入主题之前先看个 Java 网络编程的一个简单例子:代码很简单,客户端和服务端进行通信,对于客户端的每次输入,服务端回复 get.注意,服务端可以同时允许多个客户端连接. 服务端端代码: // 创 ...

  9. Java IO模型

    Linux的内核将所有外部设备都看做一个文件来操作,对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符).而对一个Socket的读写也会有相应的描述 ...

随机推荐

  1. 关于COM的Unicode string的精彩论述

    I need to make a detour for a few moments, and discuss how to handle strings in COM code. If you are ...

  2. rapidxml 节点加入另一个xml

    void TestRapidXml() { ]; sprintf(xmlContent,"<root><head>aaa</head><body&g ...

  3. Android运行机制

    一. Android平台各层 Android平台架构图,如下图:由上到下依次为应用程序.应用程序框架.库.Android运行时.Linux内核. 1.Linux内核: Android系统基于Linux ...

  4. access2003的使用

    access2003中如何用sql语句创建表 http://zhidao.baidu.com/link?url=dinVbwoI20Xz__NbcIeBPdkjeXRWmZNB0xJvdr0eMBqN ...

  5. Appium Python 六:管理应用和Activity

    管理应用 1. 将当前应用放到后台 执行之后,应用会被放到后台特定时间.比如这里就是5秒,5秒过后,应用会重新回到前台. driver.background_app(5) 官网示例: driver.b ...

  6. cp 命令(转)

    原文:http://www.cnblogs.com/peida/archive/2012/10/29/2744185.html cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情 ...

  7. 栈的应用实例——计算后缀表达式

    用户输入一个后缀表达式,程序计算该后缀表达式的值并输出结果: /* postfix_expression.c */ #include "stack.h" #include < ...

  8. vue 笔记一

    vue: 读音: v-u-e view vue到底是什么? 一个mvvm框架(库).和angular类似 比较容易上手.小巧 mvc: mvp mvvm mv* mvx 官网:http://cn.vu ...

  9. mysql 运行计划explain具体解释

    explain主要是用来获取一个query的运行计划,描写叙述mysql怎样运行查询操作.运行顺序,使用到的索引,以及mysql成功返回结果集须要运行的行数.能够帮助我们分析 select 语句,让我 ...

  10. notify notifyAll 死锁

    从一个死锁分析wait,notify,notifyAll 泡芙掠夺者 关注 2017.08.24 22:00* 字数 1361 阅读 249评论 3喜欢 7赞赏 1 本文通过wait(),notify ...