前言
之前一篇文章简单介绍了NIO,并附了一个简单的例子,但是自己试一下就会知道,简单的使用NIO是无法满足开发需要的,因为NIO处理的思路和日常servlet加spring中习惯的一连接一线程有很大不同。
NIO与多线程
上篇那个例子实现了一个简单的NIO,但是实际使用中我们不可能仅仅在单线程下使用,肯定会使用多线程提高处理的效率,但是这样就会有几个难点。
Readable和Writeable的空触发
之前的文章的代码有写到通过key去判断readable和writeable这两个事件,从而去读写,但是会出现以下情况
- 实际上这2个事件并不像看上去那样,在writeable之中负责写内容,以最常用的http的请求-返回场景来看,通常上返回的处理是在read处理完后写内容到channel里去,writeable里只做一个flush操作,并不是readable只负责读,writeable只负责写。
- 在多线程下,这两个事件的处理尤为糟糕,并不能简单的去实现Runable再套用函数进去执行,因为这两个事件本身在key被remove前,会一直触发,如果第一个执行的线程执行完之前,这个key因为没有remove被再次获取到去执行,那么可能就会产生很多问题,比如读取不到数据(已经被第一个线程读取了),channel已经关闭(第一个线程或其他线程写完后,本机或者远端关闭了连接)。这样都会影响多线程实际执行。
- Readable和Writeable事件产生一般对应着待读数据的到来和待写数据的就绪,就绪后产生key提醒应用去处理。但是有2种情况下会产生实际