程序员

java NIO详解

2017-12-27  本文已影响0人  rockjh

概述

BIO是面向字节流和字符流的,数据从流中顺序获取

NIO是面向通道和缓冲区的,数据总是从通道中读到buffer缓冲区内,或者从buffer缓冲区内写入通道

Channel通道和Buffer缓冲区是NIO的核心,几乎在每一个IO操作中使用它们,Selector选择器则允许单个线程操作多个通道,对于高并发多连接很有帮助。

操作系统的IO一般分为两个阶段,等待和就绪操作,比如读可以分为等待系统可读和真正的读,写可以分为等待系统可写和真正的写,在传统的BIO中是这两个阶段都会阻塞,在NIO中第一个阶段不是阻塞的,第二个阶段是阻塞的,如下图,BIO是阻塞IO,NIO是非阻塞IO

nio.jpg

Buffer(缓冲区)

常用Buffer类型

ByteBuffer,MappedByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer。对应了几大基本数据类型

ByteBuffer可以选择实例化为DirectByteBuffer和HeapByteBuffer,如果数据量比较小的中小应用情况下,可以考虑使用heapBuffer;反之可以用directBuffer。一般来说DirectByteBuffer可以减少一次系统空间到用户空间的拷贝。但Buffer创建和销毁的成本更高,更不宜维护,通常会用内存池来提高性能。其他buffer类似

利用Buffer读写数据步骤

buffer的属性

buffer_modes.png

buffer api

Channel(通道)

Channel的重要实现

Scatter和Gather

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body };
channel.read(bufferArray);
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
//write data into buffers
ByteBuffer[] bufferArray = { header, body };
channel.write(bufferArray);

在有些场景会非常有用,比如处理多份需要分开传输的数据,举例来说,假设一个消息包含了header和body,我们可能会把header和body分别放在不同的buffer

Selector(选择器)

Selector用于检查一个或多个NIO Channel的状态是否可读可写,这样就可以实现单线程管理多个Channels,也就是可以管理多个网络连接,NIO非阻塞主要就是通过Selector注册事件监听,监听通道将数据就绪后,就进行实际的读写操作,因此前面说的IO两个阶段,一阶段NIO仅仅是异步监听,二阶段就是同步实际操作数据

Selector监听事件类别

使用Selector的步骤

需要使用Selector的Channel必须是非阻塞的,FileChannel不能切换为非租塞的,因此FileChannel不适用于Selector

API

Issues

我们可以理解为本机有三块网卡,一块网卡叫做 loopback(这是一块虚拟网卡)127.*整个网段用作loopback网络接口的默认地址,按照惯例通常设置为127.0.0.1这个地址和网络无关,这个是环回地址,直接找本地地址,如果服务端绑定这个地址,那就只有本地服务器才可以访问这个服务端,另外一块网卡叫做 ethernet (这是你的有线网卡),还有一块网卡叫做 wlan(这是你的无线网卡)

实例源代码如下图:前往下载

demo.png
上一篇 下一篇

猜你喜欢

热点阅读