图说NIO(同步非阻塞IO)-基础和概述

本文介绍了Java NIO的基础知识,包括NIO与传统BIO的区别,重点讲解了Buffer、Channel和Selector的概念及作用。Buffer作为数据交换的核心,通过其属性和API实现数据读写。Channel提供了双向数据传输能力,而Selector允许单线程处理多个客户端连接,降低了系统开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述:

JDK1.4引入的一种IO模式,是一种非阻塞的,面向缓冲区,基于通道的一种IO,以Channel( 通道) ,Buffer( 缓冲区), Selector( 选择器) 为核心


和传统IO(BIO)的对比:

先上图
BIO和NIO的区别
       观察上图,我们可以看出,传统的IO呢,他完全是基于流的方式在处理数据,就好比一根管子,比如我们拿吸管喝可乐,你要么就是吸,要么就是往你可乐杯子里面吐,不能做其他的,是一种单向的操作,你现在在吐,但是你想吸的话,你必须等你吐完了才能吸,你一时间只能做一件事。
       而观察第二幅图,就比第一幅图丰富多了,对比第一幅图BIO,你可以观察到服务端面向多个客户端是用了3条线程,第二幅图咋一看也是,实际上不是的,NIO面对3个客户端只创建了一条线程,为什么这样呢?其中不得不说他的一些概念,它不像传统IO直接和流进行交互,它是和selector(选择器)交互,然后selector通过监听channel(管道),channel基于buffer(缓冲区)配合来进行读写数据(BIO是单向的,要么写要么读,NIO是双向的),这里多少说得有点粗糙,下面进行一一说明。


Buffer(缓冲区):

Buffer和Channel
上图说明:
       蓝色边白色的空心代表Channel(管道),中间的一块区域是Buffer(缓冲区),这个图我觉得我表达出了Channel是一个端到端交互的一个连接,本质上还是一个流,但是这个流不是和传统的流一样,单个管道的,而是通过流入Buffer里面,进行缓存,两端再根据需要是读取还是写入,反正都会先经过管道再经过缓存,形成了一个管道,两种功效(读写可同时进行)

Buffer类似于数组,有多种类型:

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

buffer的属性和api

  • public static ByteBuffer allocate(int capacity)
    给buffer分配一个容量为 capacity 的空间
  • public final int position();
    数组的当前位置,刚初始化buffer的时候,这个值为0,代表着下一次要操作元素的位置是0,也就是第一位,如果加入4个字节,那么在这个数组没有归位之前,我们数组前4为就被占住了,那么当前position也就是我们下次能操作的位置也就是4(0,1,2,3被占住)
  • public final int limit();
    可以理解为存有数据的界限吧,缓冲区数组中不可操作的下一个元素的位置

Buffer clear() 清空缓冲区并返回对缓冲区的引用
Buffer flip() 为 将缓冲区的界限设置为当前位置,并将当前位置充值为 0
int capacity() 返回 Buffer 的 capacity 大小
boolean hasRemaining() 判断缓冲区中是否还有元素
int limit() 返回 Buffer 的界限(limit) 的位置
Buffer limit(int n) 将设置缓冲区界限为 n, 并返回一个具有新 limit 的缓冲区对象
Buffer mark() 对缓冲区设置标记
int position() 返回缓冲区的当前位置 position
Buffer position(int n) 将设置缓冲区的当前位置为 n , 并返回修改后的 Buffer 对象
int remaining() 返回 position 和 limit 之间的元素个数
Buffer reset() 将位置 position 转到以前设置的 mark 所在的位置
Buffer rewind() 将位置设为为 0, 取消设置的 mark

在这里插入图片描述
可以写点demo,往里面加数据,观察buffer的变化,直接输出buffer可以看到里面对应的一些属性,它重写了toString()的,这里不多赘述,不知咋讲,又浪费时间。

【补充】
我们上面用的ByteBuffer.allocate(num);是 非直接缓存 ,还有一种ByteBuffer.allocateDirect(num) 是属于 直接缓存 ,适用于并发场景下和大数据存储下。


Channel:

可以理解为:可以异步读写和buffer交流的双向流
分类:

  • FileChannel:用于读取、写入、映射和操作文件的通道。
  • DatagramChannel:通过 UDP 读写网络中的数据通道。
  • SocketChannel:通过 TCP 读写网络中的数据。
  • ServerSocketChannel:可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel。 【ServerSocketChannel 类似 ServerSocket , SocketChannel 类似 Socket】
    其实有很多例子的,就是demo,我觉得说起来太费劲了,我就不说了,主要是这个帖子写来就是我复习用的,不太适合别人阅读吧!

Selector

  • Java 的 NIO,用非阻塞的 IO 方式。可以用一个线程,处理多个的客户端连接,就会使用到 Selector(选择器)
  • Selector 能够检测多个注册的通道上是否有事件发生(注意:多个 Channel 以事件的方式可以注册到同一个
    Selector),如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管
    理多个通道,也就是管理多个连接和请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值