(六)NIO编程--1篇

懒驴 2021年12月06日 1,583次浏览

首先先抛出一个问题:少量的线程如何同时为大量连接服务呢?
答案就是:就绪选择。这就好比到餐厅吃饭,每来一桌客人,就有一个服务员专门服务,从你进餐厅到最后结账走人。这种方式的好处就是服务质量好,一对一的VIP服务,可是缺点也很明显,成本高。如果餐厅生意好,同时来100桌客人,那么就需要100个服务员了,老板发工资的成本就很高了。这就是传统的一个连接一个线程的方式。
上面的例子,怎么可以让10个人服务员同时服务100桌客人呢?其实不难发现,服务员在为客人服务的过程中并不是一直都忙着的,客人点完菜,上完菜,吃着的这段时间,服务员就闲下来了。可是这个时候这个服务员还是被这桌人占用着的,不能为别人服务。怎么把这段闲着的时间利用起来呢?餐厅老板就想了一个办法,让一个服务员(前台)专门负责收集客人的需求,登记下来。比如有客人进来、点菜、结账,都先记录下来按顺序排好。每个服务员到这里领一个需求。比如点菜,服务员拿着菜单帮客人点菜去了。客人点好菜以后,服务员马上回来,领取下一个需求,继续为别人的客人服务。这种服务方式质量不如一对一的服务,当客人需求很多的时候就需要等待。但好处也很明显,由于客人吃饭时服务员不用闲着,因此服务员这段时间内可以Wie其他客人服务。原来10个服务员最多同时为10桌客人服务,现在可以同时为50桌客人服务了。
这种服务方式跟传统服务的区别有两个:

  1. 增加了一个角色:专门负责收集客人需求的人。NIO里对应的就是Selector
  2. 由阻塞服务变为非阻塞服务,客人吃着的时候服务员不要一直候在客人旁边。传统的IO操作,比如read(),当没有数据可读的时候,线程一直阻塞被占用,直到有数据到来。NIO中没有数据可读时,read()会立即返回0,线程不会阻塞。

NIO中客户端创建一个连接后,先要将连接注册到Selector。相对于客人进入餐厅后,告诉前台需要用餐。前台会告之桌号,然后到达对应的桌子坐下,SelectionKey就是桌号。当某一桌需要服务时,前台就记录那一桌需要什么服务。比如1号桌要点菜、2号桌要结账,服务员从前台取一条记录,根据记录提供服务,服务完了再来取下一条需求。这样服务的时间就被有效地利用起来了。
NIO通信模型