线程池固然可以解决这个问题,万一需求量还不够还要扩大线程池。当是这是我们自己靠着自己的思想完成的 IO 操作,Socket 上来了就去创建线程去抢夺CPU 资源,MD,线程都 TM 做IO 去了,CPU 也不舒服呀。
这时呢:Jdk 官方坐不住了,兄弟 BIO 的问题交给我,我来给你解决:NIO 的诞生使用 NIO 实现网络通信。
NIO 是 JDK1.4 提供的操作,他的流还是流,没有改变,服务器实现的还是一个连接一个线程,当是:客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 I/O 请求时才启动一个线程进行处理。NIO 方式适用于连接数目多 且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4 之后开始支持。
看不懂介绍可以认真看看代码实例,其实不难
Channel 是一个对象,可以通过它读取和写入数据。 通常我们都是将数据写入包含一个或者多个字节的缓冲区,然后再将缓存区的数据写入到通道中,将数据从通道读入缓冲区,再从缓冲区获取数据。
Channel 类似于原 I/O 中的流(Stream),但有所区别:
流是单向的,通道是双向的,可读可写。
流读写是阻塞的,通道可以异步读写。
Selector 可以称他为通道的集合,每次客户端来了之后我们会把 Channel 注册到Selector 中并且我们给他一个状态,在用死循环来环判断(判断是否做完某个操作,完成某个操作后改变不一样的状态)状态是否发生变化,知道 IO 操作完成后在退出死循环
Buffer 是一个缓冲数据的对象, 它包含一些要写入或者刚读出的数据。
在普通的面向流的 I/O 中,一般将数据直接写入或直接读到 Stream 对象中。当是有了 Buffer(缓冲区)后,数据第一步到达的是 Buffer(缓冲区)中
缓冲区实质上是一个数组(底层完全是数组实现的,感兴趣可以去看一下)。通常它是一个字节数组,内部维护几个状态变量,可以实现在同一块缓冲区上反复读写(不用清空数据再写)