JAVA NIO(一)
1 NIO概述
1.1NIO(new IO)是一个可以替代java IO API的API,NIO提供了与标准IO不同的工作方式,标准IO是基于字节流和字符流进行操作的,而NIO是基于channel和Buffer进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写到通道中,方式如例图示,JAVA NIO的几个核心组成部分是channels,Buffers,Selectors。
1.2NIO中的channel有好几种类型包括:FileChannel,DatagramChannel,SocketChannel,ServerSocketChannel这些channel涵盖了UDP,TCP,以及文件IO;Buffer包括ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer,这些buffer,覆盖了所有的基本数据类型,还有一种映射MappedByteBuffer,在此我们不做细说;Selector,selector允许单线程处理多个Channel,如下图样例,要使用Selector,得先向Selector注册channel,然后调用selector()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
1.3和传统IO相比, NIO是非阻塞 IO,NIO中非阻塞I/O采用了基于Reactor模式的工作方式,I/O调用不会被阻塞,相反是注册感兴趣的特定I/O事件,如可读数据到达,新的套接字连接等等,在发生特定事件时,系统再通知我们。NIO中实现非阻塞I/O的核心对象就是Selector,Selector就是注册各种I/O事件地 方,而且当那些事件发生时,就是这个对象告诉我们所发生的事件,如下图所示:
如图所示,当有读或写等任何注册的事件发生时,可以从Selector中获得相应的SelectionKey,同时从 SelectionKey中可以找到发生的事件和该事件所发生的具体的SelectableChannel,以获得客户端发送过来的数据。非阻塞指的是IO事件本身不阻塞,但是获取IO事件的select()方法是需要阻塞等待的.区别是阻塞的IO会阻塞在IO操作上, NIO阻塞在事件获取上,没有事件就没有IO, 从高层次看IO就不阻塞了.也就是说只有IO已经发生那么我们才评估IO是否阻塞,但是select()阻塞的时候IO还没有发生,何谈IO的阻塞呢?NIO的本质是延迟IO操作到真正发生IO的时候,而不是以前的只要IO流打开了就一直等待IO操作。
2NIO工作原理
1. 由一个专门的线程来处理所有的 IO 事件,并负责分发。
2. 事件驱动机制:事件到的时候触发,而不是同步的去监视事件。
3. 线程通讯:线程之间通过 wait,notify 等方式通讯。保证每次上下文切换都是有意义的。减少无谓的线程切换。
java NIO的服务端只需启动一个专门的线程来处理所有的 IO 事件java NIO采用了双向通道(channel)进行数据传输,而不是单向的流(stream),在通道上可以注册我们感兴趣的事件。一共有以下四种事件:
事件名 | 对应值 |
服务端接收客户端连接事件 | SelectionKey.OP_ACCEPT(16) |
客户端连接服务端事件 | SelectionKey.OP_CONNECT(8) |
读事件 | SelectionKey.OP_READ(1) |
写事件 | SelectionKey.OP_WRITE(4) |
服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件。我们以服务端为例,如果服务端的selector上注册了读事件,某时刻客户端给服务端发送了一些数据,阻塞I/O这时会调用read()方法阻塞地读取数据,而NIO的服务端会在selector中添加一个读事件。服务端的处理线程会轮询地访问selector,如果访问selector时发现有感兴趣的事件到达,则处理这些事件,如果没有感兴趣的事件到达,则处理线程会一直阻塞直到感兴趣的事件到达为止。
3NIO使用步骤
3.1NIOserver端使用步骤
3.2NIOClinet端使用步骤