net stock interview (E-C) mp3,谁知道出自哪里?哪里有翻译?

sql遇到个很奇怪的问题大佬们求助!!! [问题点数:50分,结帖人qq_]


匿名用户不能发表回复!

摘要: 基础概念 ? 缓冲区操作 缓沖区及操作是所有I/O的基础进程执行I/O操作,归结起来就是向操作系统发出请求让它要么把缓冲区里的数据排干(写),要么把缓冲区填滿(读)如下图 ? 内核空间、用户空间  上图简单描述了数据从磁盘到用户进程的内存区域移动的过程,其间涉及到了内核空间与用户空間

缓冲区及操作是所有I/O的基础,进程执行I/O操作归结起来就是向操作系统发出请求,让它要么把缓冲区里的数据排干(写)要么把缓沖区填满(读)。如下图

? 内核空间、用户空间 
上图简单描述了数据从磁盘到用户进程的内存区域移动的过程其间涉及到了内核空间与鼡户空间。这两个空间有什么区别呢 
用户空间就是常规进程(如JVM)所在区域,用户空间是非特权区域如不能直接访问硬件设备。内核涳间是操作系统所在区域那肯定是有特权啦,如能与设备控制器通讯控制用户区域的进程运行状态。进程执行I/O操作时它执行一个系統调用把控制权交由内核。 
说起I/O模型网络上有一个错误的概念,异步非阻塞/阻塞模型其实异步根本就没有阻不阻塞之说,异步模型就昰异步模型让我们来看一看Rihard Stevens在其UNIX网络编程卷1中提出的5个I/O模型吧。




由POSIX术语定义同步I/O操作导致请求进程阻塞,直到I/O操作完成;异步I/O操作不導致请求进程阻塞5种模型中的前4种都属于同步I/O模型。
开始讲NIO之前了解为什么会有NIO,相比传统流I/O的优势在哪它可以用来做什么等等的問题,还是很有必要的
传统流I/O是基于字节的,所有I/O都被视为单个字节的移动;而NIO是基于块的大家可能猜到了,NIO的性能肯定优于流I/O没錯!其性能的提高 要得益于其使用的结构更接近操作系统执行I/O的方式:通道和缓冲器。我们可以把它想象成一个煤矿通道是一个包含煤層(数据)的矿藏,而缓冲器则是派送 到矿藏的卡车卡车载满煤炭而归,我们再从卡车上获得煤炭也就是说,我们并没有直接和通道茭互;我们只是和缓冲器交互并把缓冲器派送到通道。通道要么 从缓冲器获得数据要么向缓冲器发送数据。(这段比喻出自Java编程思想)
NIO的主要应用在高性能、高容量服务端应用程序典型的有Apahe Mina就是基于它的。
缓冲区实质上就是一个数组但它不仅仅是一个数组,缓冲区還提供了对数据的结构化访问而且还可以跟踪系统的读/写进程。为什么这么说呢下面来看看缓冲区的细节。 
讲缓冲区细节之前我们先来看一下缓冲区“家谱”:

缓冲区对象有四个基本属性: 
o 容量apaity:缓冲区能容纳的数据元素的最大数量,在缓冲区创建时设定无法更改 
o 仩界Limit:缓冲区的第一个不能被读或写的元素的索引 
o 位置Position:下一个要被读或写的元素的索引 

Soket通道可以运行非阻塞模式并且是可选择的,非阻塞I/O与可选择性是紧密相连的这也正是管理阻塞的API要在 Seletablehannel中定义的原因。设置非阻塞非常简单只要调用onfigureBloking(false)方法即可。如果需要中 途更改阻塞模式那么必须首先获得blokingLok()方法返回的对象的锁。 
ServerSokethannel是一个基于通道的soket监听器但它没有bind()方法,因此需要取出对等的Soket对象并使用它来 绑定到某┅端口以开始监听连接在非阻塞模式下,当没有传入连接在等待时其aept()方法会立即返回null。正是这种检查连接而不阻塞的能力实 现了可伸縮性并降低了复杂性选择性也因此得以实现。


  

相对于ServerSokethannel它扮演客户端,发起到监听服务器的连接连接成功后,开始接收数据 
要注意嘚是,调用它的open()方法仅仅是打开但并未连接要建立连接需要紧接着调用onnet()方法;也可以两步合为一步,调用open(SoketAddress remote)方法 
不同于前面两个通道对潒,它是无连接的它既可以作为服务器,也可以作为客户端 
选择器提供选择执行已经就绪的任务的能力,这使得多元I/O成为可能就绪選择和多元执行使得单线程能够有效率地同时管理多个I/O通道。选择器可谓NIO中的重头戏I/O复用的核心,下面我们来看看这个神奇的东东
我們先来看下选择器相关类的关系图:

由图中可以看出,选择器类Seletor并没有和通道有直接的关系而是通过叫选择键的对象SeletionKey来联系的。选择键玳表了通道与选择 器之间的一种注册关系hannel()和seletor()方法分别返回注册的通道与选择器。由类图也可以看出一个通道可以注册到多个选择器;紸 册方法register()是放在通道类里,而我感觉放在选择器类里合适点 
非阻塞特性与多元执行的关系非常密切,如果在阻塞模式下注册一个通道系统会抛出IllegalBlokingModeExeption异常。 
那么通道注册到选择器后,选择器又是如何实现就绪选择的呢真正的就绪操作是由操作系统来做的,操作系统处理I/O請求并通知各个线程它们的数据已经准备好了而选择器类提供了这种抽象。 
选择键作为通道与选择器的注册关系需要维护这个注册关系所关心的通道操作interestOps()以及通道已经准备好的操作readyOps(),这 两个方法的返回值都是比特掩码另外ready集合是interest集合的子集。选择键类中定义了4种可选擇操作:read、write、 回过头来再看下注册方法其第二个参数是一个比特掩码,这个参数就是上面讲的这个注册关系所关心的通道操作在选择過程中,所关心的通道操作可以由方法 interestOps(int operations)进行修改但不影响此次选择过程(在下一次选择过程中生效)。 
类图中可以看出选择器类中维護着两个键的集合:已注册的键的集合keys()和已选择的键的集合seletedKeys(),已选择的键的集合是已注 册的键的集合的子集已选择的键的集合中的每个荿员都被选择器(在前一个选择操作中)判断为已经准备好(所关心的操作集合中至少一个操作)。 除此之外其实选择器内部还维护着┅个已取消的键的集合,这个集合包含了anel()方法被调用过的键 
选择器类的核心是选择过程,基本上来说是对selet()、poll()等系统调用的一个包装那麼,选择过程的具体细节或步骤是怎样的呢 
当选择器类的选择操作selet()被调用时,下面的步骤将被执行: 
1.已被取消的键的集合被检查如果非空,那么该集合中的键将从另外两个集合中移除并且相关通道将被注销。这个步骤结束后已取消的键的集合将为空。 
2.已注册的键的集合中的键的interest集合将被检查在这个步骤执行过后,对interset集合的改动不会影响剩余的检查过程一旦就绪条件被 确定下来,操作系统将会进荇查询以确定每个通道所关心的操作的真实就绪状态。这可能会阻塞一段时间最终每个通道的就绪状态将确定下来。那些还没有准备 恏的通道将不会执行任何操作;而对于那些操作系统指示至少已经准备好interest集合中的一个操作的通道将执行以下两种操作中的一种: 
a.如果通道的键还没有在已选择的键的集合中,那么键的ready集合将被清空然后表示操作系统发现的当前通道已经准备好的操作的比特掩码将被设置。 
b.如果通道的键已处于已选择的键的集合中键的ready集合将被表示操作系统发现的当前通道已经准备好的操作的比特掩码所更新,所有之湔的已经不再是就绪状态的操作不会被清除 
3.步骤2可能会花费很长时间,特别是调用的线程处于休眠状态同时,与选择器相关的键可能會被取消当步骤2结束时,步骤1将重新执行以完成任意一个在选择过程中,键已经被取消的通道的注销 
4.selet操作返回的值是ready集合在步骤2中被修改的键的数量,而不是已选择键的集合中的通道总数返回值不是已经准备好的通道的总数,而是 从上一个selet调用之后进入就绪状态的通道的数量之前调用中就绪的,并且在本次调用中仍然就绪的通道不会被计入 
选择器类提供了方法wakeup(),可以使线程从被阻塞的selet()方法中优雅的退出它将选择器上的第一个还没有返回的选择操作立即返回。 
调用选择器类的lose()方法那么任何一个阻塞在选择过程中的线程将被唤醒,与选择器相关的通道将被注销而键将被取消。 
? 选择过程的可扩展性 
在单pu中使用一个线程为多个通道提供服务可能是个好主意但對于多pu的系统,单线程必然比多线程在性能上要差很多 
一个比较不错的多线程策略是,以所有的通道使用一个选择器(或多个选择器視情况),并将以就绪通道的服务委托给其他线程用一个线程监控通道的就绪状态,并使用一个工作线程池来处理接收到的数据讲了這么多,下面来看一段用NIO写的简单服务器代码:


  

o 某个事件处理者宣称它对某个soket上的读事件很感兴趣; 
o 事件分离者等着这个事件的发生; 
o 当事件發生了事件分离器被唤醒,这负责通知先前那个事件处理者; 
o 事件处理者收到消息于是去那个soket上读数据了. 如果需要,它再次宣称对这个soket仩的读事件感兴趣一直重复上面的步骤; 
o 事件处理者直接投递发一个写操作(当然,操作系统必须支持这个异步操作). 这个时候事件处理者根本不关心读事件,它只管发这么个请求它魂牵梦萦的是这个写操作的完成事件。这个处理者很拽发个命令就不管具体的事情了,只等着别人(系统)帮他搞定的时候给他回个话 
o 事件分离者等着这个读事件的完成(比较下与Reator的不同); 
o 当事件分离者默默等待完成事情到来的哃时,操作系统已经在一边开始干活了它从目标读取数据,放入用户提供的缓存区中最后通知事件分离者,这个事情我搞完了; 
o 事件分享者通知之前的事件处理者: 你吩咐的事情搞定了; 
o 事件处理者这时会发现想要读的数据已经乖乖地放在他提供的缓存区中想怎么处理都行叻。如果有需要事件处理者还像之前一样发起另外一个写操作,和上面的几个步骤一样 
异步的proator固然不错,但它局限于操作系统(要支歭异步操作)为了开发真正独立平台的通用接口,我们可以通过reator模拟来实现proator
o 把数据已经准备好的消息给用户处理函数,即事件处理者(Proator 偠做的) 
本文介绍了 I/O的一些基础概念及5种I/O模型NIO是5种模型中的I/O复用模型;接着进入主题Java NIO,分别讲了NIO中三个最重要的概念:缓冲区、通道、选擇器;我们也明白了NIO是如何实现I/O复用模型的最后讨论了I/O多路复用模式中的两 种模式:reator和proator,以及如何用reator模拟proator

我要回帖

更多关于 C.E 的文章

 

随机推荐