1,Java NIO
Java non-blocking IO 即 非阻塞IO,线程在等待的时候,可以做其他的事情。
2,IO 对比NIO
IO 是面向流,NIO 是面向缓冲
面向流是指每次从流中读出一个或者多个字节,直到全部读出为止
面向缓冲区是指将数据先存到一个缓存区
IO 是阻塞, NIO 是非阻塞
IO: 当线程调用read() 或者write() 的时候,只有当数据被读取或者完全写入,否则该线程在此期间干不了其他事情。
NIO: 一个线程向通道发送请求读取数据开始,直到数据变的可以读取之前,线程不会阻塞,可以一直做其他事情。
3,IO 与 NIO 的选择
每次发送少量数据,但是需要建立多个通道的情况,例如聊天室,这种情况适合用NIO
大量数据,少量连接,这种情况适合用IO
4,NIO有三个核心模块:Selector(选择器)、Channel(通道)、Buffer(缓冲区);
Buffer:与Channel 进行交互时,需要将数据从Channel 读取到Buffer,从Buffer 写入到Channel,缓冲区本质上是一块可以存取数据的内存,只是被包装成了NIO Buffer 对象,提供一些方法,可以访问。
缓冲区基本类型:ByteBuffer;CharBuffer;ShortBuffer;IntBuffer;LongBuffer;FloatBuffer;DoubleBuffer;
Channel: Channel好比IO 流的模拟,任何数据read() 或者write(),都必须通过Channel对象。
Selector:NIO 用select 机制,不用为每一个客户端连接新的线程处理,而是将其注册到Selector 对象中,这样单线程利用Selector 对象管理大量的并发的网络连接。
当有读写或时间发生时候,可以从Selector对象中获得一个SelectorKey 通过这个SelectorKey 可以找到具体的Channel 来获取从客户端传过来的数据。
通道和缓冲区的机制,使得线程无需阻塞地等待IO事件的就绪,但是总是要有人来监管这些IO事件。这个工作就交给了selector来完成,这就是所谓的同步。
要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪,这就是所说的轮询。一旦这个方法返回,线程就可以处理这些事件。
Selector中注册的感兴趣事件有:
-
OP_ACCEPT:即连接事件(TCP 连接), 对应于SelectionKey.OP_CONNECT;
-
OP_CONNECT :即确认事件, 对应于SelectionKey.OP_ACCEPT;
-
OP_READ :即读事件, 对应于SelectionKey.OP_READ, 表示 buffer 可读.
-
OP_WRITE:即写事件, 对应于SelectionKey.OP_WRITE, 表示 buffer 可写.