系统I/O 可分为阻塞型(BIO), 非阻塞同步型(NIO)以及非阻塞异步型(AIO).
阻塞型I/O(BIO)意味着控制权只到调用操作结束了才会回到调用者手里. 结果调用者被阻塞了, 这段时间了做不了任何其它事情. 更郁闷的是,在等待IO结果的时间里,调用者所在线程此时无法腾出手来去响应其它的请求,这真是太浪费资源了。拿read()操作来说吧, 调用此函数的代码会一直僵在此处直至它所读的socket缓存中有数据到来.
相比之下,非阻塞同步(NIO)是会立即返回控制权给调用者的。调用者不需要等等,它从调用的函数获取两种结果:要么此次调用成功进行了;要么系统返回错误标识告诉调用者当前资源不可用,你再等等或者再试度看吧。比如read()操作, 如果当前socket无数据可读,则立即返回EWOULBLOCK/EAGAIN,告诉调用read()者"数据还没准备好,你稍后再试".
在非阻塞异步调用中,稍有不同。调用函数在立即返回时,还告诉调用者,这次请求已经开始了。系统会使用另外的资源或者线程来完成这次调用操作,并在完成的时候知会调用者(比如通过回调函数)。拿Windows的ReadFile()或者POSIX的aio_read()来说,调用它之后,函数立即返回,操作系统在后台同时开始读操作。
面向流与面向缓冲
Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)
为了支持非阻塞的异步IO,有两种方式,一是操作系统支持异步IO,能够帮助处理IO的读写,第二种是写程序模拟异步IO,将非阻塞的同步IO改成异步IO。TProactor方案帮组实现的异步IO,可以在不同的操作系统都提供异步IO功能,并且对外提供统一的接口
BIO、NIO、AIO适用场景分析:
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
AIO研究 http://www.tuicool.com/articles/Z3URbu
http://www.cnblogs.com/pigerhan/p/3532695.html
http://www.iteye.com/topic/472333
Epoll 详解
epoll的高效就在于,当我们调用epoll_ctl往里塞入百万个句柄时,epoll_wait仍然可以飞快的返回,并有效的将发生事件的句柄给我们用户。这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。 而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已,如何能不高效?!那么,这个准备就绪list链表是怎么维护的呢?当我们执行epoll_ctl时,除了把socket放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的 中断到了,就把它放到准备就绪list链表里。所以,当一个socket上有数据到了,内核在把网卡上的数据copy到内核中后就来把socket插入到准备就绪链表里了。(Epoll 实现了异步IO)
支持一个进程打开大数目的socket描述符(FD):select 最不能忍受的是一个进程所打开的FD是有一定限制的,由FD_SETSIZE设置,默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。这时候你一是可以选择修改这个宏然后重新编译内核,不过资料也同时指出这样会带来网络效率的下降,二是可以选择多进程的解决方案(传统的 Apache方案),不过虽然linux上面创建进程的代价比较小,但仍旧是不可忽视的,加上进程间数据同步远比不上线程间同步的高效,所以也不是一种完美的方案。不过 epoll则没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
IO效率不随FD数目增加而线性下降:传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是"活跃"的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其他idle状态socket则不会,在这点上,epoll实现了一个"伪"AIO,因为这时候推动力在os内核。在一些 benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境,epoll并不比select/poll有什么效率,相反,如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。
使用mmap加速内核与用户空间的消息传递:这点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注epoll的话,一定不会忘记手工 mmap这一步的
内核微调:这一点其实不算epoll的优点了,而是整个linux平台的优点。也许你可以怀疑linux平台,但是你无法回避linux平台赋予你微调内核的能力。比如,内核TCP/IP协议栈使用内存池管理sk_buff结构,那么可以在运行时期动态调整这个内存pool(skb_head_pool)的大小--- 通过echo XXXX>/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参数(TCP完成3次握手的数据包队列长度),也可以根据你平台内存大小动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网卡驱动架构。
http://blog.csdn.net/xiajun07061225/article/details/9250579
http://www.cnblogs.com/debian/archive/2012/02/16/2354454.html
http://www.cnblogs.com/debian/archive/2012/02/16/2354469.html
Select实现
http://blog.csdn.net/zi_jin/article/details/4214359
http://www.cnblogs.com/moonvan/archive/2012/05/26/2518881.html
http://blog.csdn.net/goldensuny/article/details/30717107
Java Nio实例
http://xm-king.iteye.com/blog/766330
相关推荐
- `java.io`:提供输入输出流处理,支持文件操作和网络通信。 - `java.awt`:图形用户界面(GUI)类库,用于创建窗口和控件。 - `java.net`:网络通信相关类,如Socket和URL。 - 其他还有`java.applet`、`java....
8. **笔试.txt**:这很可能是包含Java基础问题的笔试题库,可能涵盖语法、类设计、异常处理、IO流、集合框架等多个方面,是检验和提升Java技能的有效工具。 通过这些文件,学习者可以全面回顾和实践Java的基础知识...
4. **IO流**:Java的输入/输出系统基于流的概念,提供了处理文件、网络数据交换的能力。掌握InputStream、OutputStream、Reader、Writer及其子类的应用,能让你处理各种数据输入输出问题。 5. **多线程**:Java提供...
Java中的IO流是进行输入/输出操作的核心机制,它涵盖了磁盘、网络、内存等多种数据传输场景。在Java中,IO流分为字符流和字节流两大类,每类又包含输入流(InputStream/Reader)和输出流(OutputStream/Writer)。本...
这份文档详细涵盖了Java编程语言的各个方面,包括基础概念、进阶特性、并发处理、内存管理、垃圾收集、集合框架、IO流、网络编程、设计模式以及框架应用等核心知识点。以下是对这些关键领域的详细阐述: 1. **Java...
为巩固对JAVA的学习,帮助大家掌握知识点,特让同学们编写一个模拟QQ在线聊天的程序JQ,可实现网上多人聊天,主要用到Swing、 线程、网络编程、集合类、文件IO处理、日期、泛型及JAVA基础知识,采用面向对象的方法...
这可能是一个2010年4月的Java复习题目集合,可能包含了选择题、填空题、简答题等多种题型,用于帮助考生复习Java的基础知识和进阶概念,如类与对象、继承、多态、异常处理、集合框架、IO流、线程、网络编程等。...
通过复习这些内容,你可以巩固对Java语言的理解,提高编程能力,并为更高级的主题(如设计模式、并发编程、网络编程等)打下坚实的基础。在实践中不断应用这些知识点,将有助于你在Java开发领域取得更大的进步。
### Java考试复习资料详解 #### 一、架构模式:B/S与C/S - **B/S架构**(Browser/Server,浏览器/服务器)是一种通过Web浏览器进行访问的应用系统架构。客户端只需要一个Web浏览器即可,无需安装任何软件。所有的...
Java期末考试复习时,应重点掌握这些基础知识,同时理解并能灵活运用类和对象的创建、继承、封装和多态性,熟悉Java集合框架的使用,理解异常处理机制,以及熟悉Java的输入输出和网络编程。通过做题和解答,可以有效...
"JAVA书本复习题答案整合"是一个精心整理的资源包,它集合了多套Java书本复习题目及其对应的答案,旨在帮助学习者高效地备考期末考核。 1. **Java基础知识**:复习题可能涵盖了Java的基础语法,如变量、数据类型、...
Java编程语言是软件开发领域广泛使用的编程语言,尤其在企业级应用中占据着主导地位。作为Java程序员,掌握基础..."JAVA程序员必读--基础篇"的CHM文件应该包含了这些内容的详细讲解,是学习和复习Java基础的宝贵资源。
5. **IO流**:输入/输出流是处理数据传输的关键,包括文件操作、网络通信等。学习Reader、Writer、InputStream、OutputStream家族,以及缓冲流、转换流的使用。 6. **多线程**:Java提供了内置的多线程支持,包括...
本压缩包提供的"Java面试资料-高清完整PDF版(集合、IO、多线程、反射前端知识、框架)"是一个全面的复习资源,涵盖了Java开发中的关键知识点。 首先,我们来详细探讨一下这些知识点: 1. **面向对象基础**:面向...
4. **IO与NIO**:Java的输入输出流体系是处理数据传输的基础,而NIO(非阻塞I/O)在高性能网络编程中尤为重要。考生需熟悉流的概念、缓冲区操作、文件读写、套接字编程等。 5. **多线程与并发编程**:Java提供了...
在准备面试时,除了简历,还要对Java相关知识进行深入复习,包括但不限于:多线程、并发编程、集合框架、设计模式、异常处理、IO流、网络编程等。同时,了解当前流行的Java框架和最佳实践,如Spring Boot、Docker、...
在Java技术领域,无论是准备笔试还是面试,理解并掌握核心的J2SE(Java Standard Edition)和J2EE(Java Enterprise Edition)知识点是至关...通过复习这些内容,并结合实际项目经验,你将更有可能在面试中脱颖而出。
Java核心测试知识点详解 ...以上内容涵盖了Java核心知识的主要方面,对于初学者和有经验的开发者都是很好的复习资源。通过深入学习和实践,可以有效提升Java编程能力,为实际项目开发打下坚实基础。
这篇复习主要涵盖了Java IO的各类概念、原理以及实际应用,旨在帮助开发者深入理解和掌握这一核心技术。 在Java中,IO操作主要用于数据的读取和写入,包括从磁盘、网络、内存等不同来源获取数据,或将数据保存到...
10. **Java标准库(JDK)**:Java开发工具包提供了大量预定义的类和接口,如util、io、lang等包,这些是编写Java程序的基础。 11. **Java应用程序类型**:Java可以编写控制台应用、图形用户界面(GUI)应用,以及...