简单聊下IO复用
没图,不分析API
Java中IO API的发展:
Socket -> SocketChannel -> AsynchronousSocketChannel
ServerSocket -> ServerSocketChannel -> AsynchronousServerSocketChannel
同步/阻塞 -> 同步/非阻塞(多路复用) -> 异步
想简单聊下多路复用。多路复用需要配合Reactor模式,前者解决技术上的问题,后者解决软件工程的问题。
技术上的问题,是将IO操作中等待和非等待的部分分开处理。我们都知道IO操作分为两个部分:
1、等待数据就绪
2、处理数据
众所周知的几种IO模型(阻塞、非阻塞、多路复用、信号驱动、异步)就是区别于这两个阶段,当需要处理很多连接的时候(高并发的情况),容易想到的是使用多线程技术,比如最简单的One-connection-Per-thread模式,但是因为等待数据不可避免,造成的结果是线程不停的休眠-唤醒的切换,导致CPU不堪重负。
IO复用的目的:将这两个阶段分开处理,让一个线程(而且是内核级别的线程)来处理所有的等待,一旦有相应的IO事件发生就通知继续完成IO操作,虽然仍然有阻塞和等待,但是等待总是发生在一个线程,这时使用多线程可以保证其他线程一旦唤醒就是处理数据,当然这需要非阻塞IO API的支持(比如非阻塞套接字)。Linux2.6之前的select,poll以及之后的epoll都是IO复用技术的实现。select和poll基本一致,epoll是对它们的改进版本。但总的来说它们都还不是真正的异步IO,因为它们在IO读写的时候仍然是阻塞的、同步的(完成一件事后才能做另外一件事)。异步IO是指“处理数据”这一阶段也是非阻塞的。Windows上的IOCP(完成端口)才是真正的AIO,理论上它比Linux的epoll更先进。
至于select、poll和epoll的区别,推荐这篇文章:http://www.cnblogs.com/Anker/p/3265058.html。简单来说:select,poll无脑的轮询,忽略了高并发下,轮询本身成了瓶颈,而epoll使用回调实现了轮询真正需要处理的连接。
Reactor模式是为了我们更简单的使用IO复用技术。它是一种并发IO模式,其他的模式还有多进程,多线程等。Reactor本身也有很多变种,比如thread per request,worker thread,thread pool,multiple reactors...网上这方面的资料很多。虽然网上关于reactor和多线程模孰优孰劣还有争论(Reactor最明显的一个缺点是无法充分利用多核的优势),但是大部分高并发的框架或组建都是基于reactor的,比如MINA,Netty,再比如Redis,Nginx(有多个工作进程来充分利用多核的优势)。关于Java中的IO复用可以看Doug Lea大神的Scalable IO in Java(http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf)。
至于JDK1.7中出现的Asynchronous I/O,只要是运行Linux上肯定无外乎epoll,那是不是可以说本质上仍然不是真正的异步IO呢?个人觉得异步这个概念是有粒度的,不可能做到完全的异步。JDK1.7中的AIO从编程的角度对程序员来说确是异步的,我们不用像在多路复用中那样自己去select了,我们需要做的就是在completion handlers中处理业务逻辑。
另外提一点:操作系统底层的IO操作都是异步的——IO中断,只不过同步更符合正常人的思维,更易于理解。
最后关于异步IO还想补充一点,虽然异步IO的第二阶段也是非阻塞的,但是仍然有优化空间。就是在数据从内核copy到用户空间这个过程,Netty就使用了Zero-Copy技术来优化这个步骤(http://my.oschina.net/plucury/blog/192577),另外还有MMAP。
欢迎斧正!
简单聊下IO复用的更多相关文章
- 简单聊下Unicode和UTF-8
今晚听同事分享提到这个,简单总结下. ## Unicode字符集 Unicode的出现是因为ASCII等其他编码码不够用了,比如ASCII是英语为母语的人发明的,只要一个字节8位就能够表示26个英文字 ...
- 简单聊下.NET6 Minimal API的使用方式
前言 随着.Net6的发布,微软也改进了对之前ASP.NET Core构建方式,使用了新的Minimal API模式.之前默认的方式是需要在Startup中注册IOC和中间件相关,但是在Minimal ...
- 一只简单的网络爬虫(基于linux C/C++)————浅谈并发(IO复用)模型
Linux常用的并发模型 Linux 下设计并发网络程序,有典型的 Apache 模型( Process Per Connection ,简称 PPC ), TPC ( Thread Per Conn ...
- Libevent的IO复用技术和定时事件原理
Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...
- IO复用(Reactor模式和Preactor模式)——用epoll来提高服务器并发能力
上篇线程/进程并发服务器中提到,提高服务器性能在IO层需要关注两个地方,一个是文件描述符处理,一个是线程调度. IO复用是什么?IO即Input/Output,在网络编程中,文件描述符就是一种IO操作 ...
- 高级IO复用应用:聊天室程序
简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户.这里采用IO复用poll技术.客户端采用了splice零拷贝.服务端采用了空间换时间(分配超大的用户数 ...
- Linux中的IO复用接口简介(文件监视?)
I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...
- IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别参考
参考https://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral IO复用,AI ...
- IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别(百度)
如果面试问到IO操作,这篇文章提到的问题,基本是必问,百度的面试官问我三个问题 (1)什么是NIO(Non-blocked IO),AIO,BIO (2) java IO 与 NIO(New IO)的 ...
随机推荐
- initWithNibName&initWithCoder &awakeFromNib&UIView常见属性方法
第一.initWithNibName这个方法是在controller的类在IB中创建,但是通过Xcode实例化controller的时候用的. 第 二.initWithCoder 是一个类在IB中创建 ...
- 浩瀚先森(guohao1206.com)
博客搬家啦,新博客地址:浩瀚先森 http://www.guohao1206.com
- error C2065: “IDD_DIALOG1” : 未声明的标识符
编译时提示error C2065: “IDD_DIALOG1” : 未声明的标识符 错误的可能原因及解决方法如下: 1.出错文件中没有包含资源文件ID声明的resource.h文件.在出错文件中加入# ...
- 发布HTML5 RTS游戏-古代战争
古代战争 游戏介绍 "古代战争"是一个2.5D即时战略游戏,使用了帝国时代2的素材,并参考了它的游戏设计和玩法. 游戏基于YEngine2D引擎开发,具备生产.建造.资源采集.战斗 ...
- Windows 2008如何绑定MAC防范ARP攻击!
Windows 2008如何绑定MAC防范ARP攻击! 阅读(1974)暂无评论时间:2010-11-23 22:52:13 在Windows server 2003时代,通过arp 这命令即 ...
- 第一章 OO大智慧
今天,正式开始读王涛写的<你必须知道的.NET(第二版)>,刚开始读了序,觉得写的相当精彩,就被吸引住了.看了一会发现本书的特点可能就是以例举例,形象生动,比较期待的样子.虽然前面讲的概念 ...
- [USACO2005][POJ2454]Jersey Politics(随机化)
题目:http://poj.org/problem?id=2454 题意:给你3*k(k<=60)个数,你要将它们分成3个长度为k的序列,使得其中至少有两个序列的和大于k*500 分析:以为有高 ...
- Linq之Expression高级篇(常用表达式类型)
目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容,上篇文章介绍了表达式树的 ...
- JavaScript基础---Cookie
内容提纲: 1.cookie 2.cookie局限性 3.其他存储 发文不易,转载请注明出处链接,谢谢! 随着Web越来越复杂,开发者急切的需要能够本地化存储的脚本功能.这个时候,第一个出现的方案:c ...
- java核心数据结构总结
JDK提供了一组主要的数据结构的实现,如List.Set.Map等常用结构,这些结构都继承自java.util.collection接口. List接口 List有三种不同的实现,ArrayList和 ...