篇一 我们讲到了bio 在高并发场景下,存在创建线程数过多的问题,因此 nio 应运而生。
nio 同步非阻塞io ,主要针对网络io 来说, 下图主要为非阻塞模型io
nio 相较于bio 采用的是事件驱动机制,通过多路复用器监听客户端的连接,读取,写入.. 事件,在事件触发时,做相应的业务处理。nio 有如下几个核心概念:
1. channel 通道,即为数据传输的通道,与bio 不同,通道为双向的,打个简单的比方,
2. byteBuffer 缓冲区, 和通道一一对应,缓冲区即为一块内存区域,和我们的 创建的ArrayList ,map 内存区域是一样的,
打个简单的比方,channel 类似于铁轨,byteBuffer 类似于火车,channel 可以往byteBuffer 读写数据,byteBuffer也可以从channel读写数据,最终我们的程序是从byteBuffer 里边读写数据。
3. selector 多路复用器,这个为nio 里边的事件驱动和线程的复用的核心组件,selector 通过监听服务端的连接事件,将客户端连接的channel 注册到selector 中,让后轮询注册的channel,监听channel 注册 的事件,从而使得一个线程可以管理多channel通道,从而减少了服务端的线程创建,
下图为一个简单的nio 服务端,只有读取客户端发送的数据,将其打印在服务端的及控制台上。有需要的朋友可以参考
public class NioServer {
public void run() throws IOException {
//服务端监听Client 连接的socket todo 异常先抛出去
ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
//多路复用器
Selector selector=Selector.open();
//绑定端口
serverSocketChannel.bind(new InetSocketAddress(8080));
// 设置serverSocketChannel 为非阻塞
serverSocketChannel.configureBlocking(false);
//往selecttor 注册连接事件监听
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 监听连接事件
while (true){
int readChannel = selector.select();
if(readChannel == 0){
System.out.println(" 暂无客户端连接 ");
continue;
}
Set<SelectionKey> selectionKeys = selector.selectedKeys();
System.out.println("长度:"+selectionKeys.size());
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey=iterator.next();
//处理连接事件
if(selectionKey.isAcceptable()){
//获取客户端连接
SocketChannel socketChannel=serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
if(selectionKey.isReadable()){
//获取socket channel
SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
//获取绑定的ByteBuffer
ByteBuffer buffer = (ByteBuffer)selectionKey.attachment();
//将channel的数据读到byteBuffer 中
socketChannel.read(buffer);
//输出客户端发送的数据
System.out.println(" 客户端:"+new String(buffer.array()));
}
//移除已处理的事件避免channel的重复注册
iterator.remove();
}
}
}
public static void main(String[] args) throws IOException {
new NioServer().run();
}
nio 还有许多可以值得挖掘的东西,类似于selector 轮询 epoll 空轮询,事件驱动,byteBuffer 数据结构,小编暂时也在学习。限于现在也是边学边分享,此篇幅暂时也无法做介绍。