C#里貌似没有这个概念吧?最近在做android的时候看到的,然后去查了下资料,有一些疑问。
首先是网上说的
java NIO非堵塞技术实际是采取Reactor模式,或者说是Observer模式为我们监察I/O端口,如果有内容进来,会自动通知我们,这样,我们就不必开启多个线程死等,从外界看,实现了流畅的I/O读写,不堵塞了。
问题1:这里说,不必开多个线程死等,我有点无法理解。一般如果做普通IO通信,比方说Socket,那么我们会给每个Socket开启一个线程,这个线程的目的是让socket做Read()时不阻塞主线程对不对?那么NIO是否是不执行这个Read()操作,或者说,是让专门一个线程,定时对所有连接做一个Read()操作,然后马上关闭Read(),执行下一个?
问题2:假如上述成立,那就是说NIO其实还是保持着Socket之间的连接?比方说有三个Socket连接到服务器,那就是开启一个数组,定时轮询这三个socket的Read()?还是说,只是保持了这三个连接的地址,需要时再连接(这个感觉不太可能,因为是服务端主动连接客户端,这个疑问是我在使用Netty4时产生的)。
问题3:关于Buffer。其实在java和C#的文件读写中都有buffer,这是否说明两者的IO都已经封装成NIO了?另外关于Buffer的工作原理,NIO本质还是基于IO的吧?而IO得Read应该是一个字节一个字节读取的,那NIO是如何使其变成一个块一个块读取的呢?我的想法是:其实本质还是一个字节一个字节读取,不过是读取了指定个数的字节后,才让Reactor触发事件,不知道是否如此?
谢谢各位大牛解答问题。个人问问题喜欢先阐述自己的想法,望纠正。
问题1,
传统阻塞式的连接方式是每个连接一个线程,当连接数较多的时候(如上千并发),线程的创建和切换所带来的开销就非常大了。
一种的解决方案就是无阻塞式的reactor模型(linux中的epoll):将所有连接放在一个线程中轮询,有读写事件的时候再执行相应的回调处理。这个主要是用在服务器端减少线程数的。 而对于客户端来说,如果socket连接不多的话,每个连接直接单独启动一个线程处理socket也是可行的。
问题2,socket连接自然是长期保存了,关闭了就没有IO事件了。
问题3,buffer和是否阻塞则没有关系。
至于.net,由于windows没有epoll之类的高效率同步api(select效率较低),它使用的是异步socket——iocp,这种方式一般称为proactor模型。具体可以参考这篇文章:http://www.ibm.com/developerworks/cn/java/j-lo-iocp/
我建议你了解下 select、poll、epool、 iocp,等你弄明白了再来重新整理你的问题。
看了下相关知识。传统的IO操作应该是TPC(Thread PerConnection)模型,而我所理解和阐述的应该属于Select模型。NIO应该就是EPOL模型了。那么说NIO其实是通过注册事件,等待事件触发的通知方式,那NIO种的Selector选择器究竟是在做什么操作呢?在我原来的理解中选择器是用来轮询每个连接的。
@Launcher: 这篇博文没多少对我有用的东西,倒是重新去看了下反应器模式,有了点收获。应该是事件通知到Selector,而不是Selector主动去轮询。不过这篇文章倒是讲到了在早期NIO中,使用的是select模型,JDK 6后才换成Epol模型。
跟C#不C#的没什么关系,是底层怎么实现无阻塞IO的问题
IO不单只网络流,还有其他,
之所以会有这个课题,是因为
一般我们要获取一个数据的时候,首先会想数据源发出一个请求.
数据源吧请求的数据返回给我们,在发出请求后,当前线程就是锁住IO,这样就造成了阻塞
无阻塞模式就是,当你对数据源发出请求后,并不等待数据源返回数据,不锁IO,
而是给这次请求注册一个响应函数,当IO返回数据时,再调用该回调函数.在请求和响应的过程中IO任然可以接受其他请求
这样来实现无阻塞IO
愚见:java的nio本质上是开了一个线程专门
轮询(如timer)在查询所有的socket的是否有数据来.
没有数据来,接着查询下一个.
------------------个人估计
简单来说,在windows平台上确实是这样,再多点限定,应该是轮询是否有注册的事件触发。不过reactor模式都是建立在操作系统的基础上实现的,不同的操作系统有不同的实现方式,在Linux系统上其实是使用事件回调进行触发的,效率要更高。查了一下午资料后得出的结论。
nio我硬是没看懂。