NIO与AIO,同步/异步,阻塞/非阻塞

1.flip(),compact(),与clear()的使用

flip()内部实现,先将limit设为当前位置,再将缓冲区的postion设为0,所以是为将缓冲区的数据写出到其它通道或者get()作准备。

clear()内部实现,将limit设为缓冲区的容量,position设为0,limit的不同为clear()与flip()的区别,所以clear()是为缓冲区的数据读入与put()作准备。当将通道中的数据读入缓冲区前,应该用clear(),不能用flip()

compact()内部实现,首先将当前位置与limit之间的数据复制到缓冲区的开始处,假设复制了n字节的数据,然后将position设为n+1,limit设为容量,所以是为了继续往缓冲区读入数据或者put()作准备,即为追加数据作准备。

flip()与compact()配合使用的例子:

1 while(channel.read(buffer)>=0 || buffer.position!=0){
2     buffer.flip();    //为写出数据作准备,将position移至0
3     channel2.write(buffer);
4     buffer.compact();    //假如上一步只写出了部分数据,此方法则可以防止数据丢失,下次读入的新数据将追加在后边
5 }

SelectionKey关于accept,connect,read,write有几个常量,这几个值都是2的整数次幂,如1,4,8,16,因此进行 | 和 ^ 运算就如同十进制中的加法和减法,这样可以灵活的注册和注销关注的事件.

如注销监听读事件,key.interestOps(key.interestOps()^SelectionKey.OP_READ)  (1|4|8)^4=9  ^优先级比|高,因此括号不能少

2.关于同步,异步,阻塞,非阻塞的区别

各种I/O模型的准确介绍:

http://blog.csdn.net/shallwake/article/details/5265287?reload

AIO介绍:还有一个相关服务器框架yanf4j :

http://www.iteye.com/topic/472333 

同步与异步的区分标准:数据从内核缓冲区(kernel buffer)复制到应用程序缓冲区(application buffer)这个阶段是否阻塞。

所以从这个角度看,阻塞I/O,非阻塞I/O,多路复用I/O,signal driven I/O(仅限于Unix)这四种I/O模型都是同步I/O.

而asynchronous I/O操作系统在copy数据到应用缓冲区完成以后才通知应用程序,所以是纯异步的。

在1.4的NIO中,阻塞的是select,I/O并不阻塞,用一个Reactor线程可以监听多个通道的事件,并分发给其它的处理线程。这个select可以看作一个代理,它会去轮询所有注册的通道事件,看事件是否已发生,所以本质上NIO可看成是同步非阻塞I/O.

NIO应用的是Reactor模式,selector是reactor,而channel可看作是事件处理程序,如读就绪事件发生时,如果通道设置的是非阻塞模式,则处理程序会将数据从内核缓冲区复制到通道中(应用缓冲区),紧接着我们在程序中从通道中读取数据时就不会阻塞了。

而NIO的同步体现在第一阶段仍然需要通过轮询来获知读/写/是否已就绪,然后事件分离器调用相应事件处理程序。

AIO的Proactor模式,不关心读就绪事件,只关心读/写完成事件,完成以后直接回调之前注册的处理程序。I/O读写,缓冲区数据的移动全部由内核完成。

在1.7的AIO中,本身也不会阻塞,对accept,read,write的调用都会立即返回,内核完成I/O操作以后,会将后续处理任务提交给线程池来执行,即回调,这个Proactor就是当初注入的AsynchronousChannelGroup,它持有这个线程池。

posted @ 2014-06-17 23:51  幽灵漫步  阅读(1946)  评论(0编辑  收藏  举报