采用传统的BIO技术,数据在写入OutputStream或者从InputStream读取时都有可能会被阻塞,一旦阻塞发生,线程将失去CPU的使用权。
解决办法:
1.一个客户端对应一个处理线程。
2.采用线程池的方法减少线程创建和回收的成本。
新的I/O操作方式:NIO
NIO中引入了channel,selector,buffer,将信息具体化。
一个线程专门负责监听客户端的连接请求,而且以阻塞的方式执行。另外一个专门负责处理请求,这个线程才会采用NIO的方式,比如Tomcat和Jetty都采用了这种方式。
Buffer的工作方式:
Selector检测到通信信道I/O有数据传输时,通过select()取得SocketChannel,将数据读取或者写入Buffer缓冲区。
如果要把缓冲区的数据写入到Channel信道,则调用byteBuffer.flip()方法。
通过Channel获取的I/O数据首先要经过操作系统的Socket缓冲区,再将数据复制到buffer中去。这个操作系统缓冲区就是底层所关联的RecvQ或者SendQ队列,从操作系统缓冲区到用户缓冲区复制数据比较消耗性能。Buffer提供了一种直接操作操作系统缓冲区的方式,即ByteBuffer.allocateDirector(size),这个方法返回的DirectByteBuffer就是与底层存储空间关联的缓冲区。
NIO还提供了FileChannel.transferTo,FileChannel.transferFrom的访问方式。与传统方式相比,减少了从内核态向用户态的复制。
FileChannel.map将文件按照一定大小块映射为内存区域,当程序访问这个内存区域时将直接操作这个文件数据。