学习NIO

https://blog.csdn.net/linsongbin1/article/details/54865371

实例:https://blog.csdn.net/yhl_jxy/article/details/79335692

netty实例:https://blog.csdn.net/javadhh/article/details/66477423

https://mp.weixin.qq.com/s?__biz=MzI0NzU3MTk2MQ==&mid=2247485753&idx=1&sn=0bb6c838d36575c20dc70fac2aa2242f&chksm=e9acbdafdedb34b90761572726137a3747264656ba1f2662a615c38c16191aca7c12b6736d24&mpshare=1&scene=1&srcid=11195roHq9T0Iq6kPP9dcA6F#rd

高并发量引起的问题

一个使用传统阻塞I/O的系统,如果还是使用传统的一个请求对应一个线程这种模式,一旦有高并发的大量请求,就会有如下问题: 
1、线程不够用,就算使用了线程池复用线程也无济于事; 
2、阻塞I/O模式下,会有大量的线程被阻塞,一直在等待数据,这个时候的线程被挂起,只能干等,CPU利用率很低,换句话说,系统的吞吐量差; 
3、如果网络I/O堵塞或者有网络抖动或者网络故障等,线程的阻塞时间可能很长。整个系统也变的不可靠;

为了说明白NIO,得先介绍一些IO模型。

在一个IO操作过程中,以read为例,会涉及到两个过程

1,等待数据准备好

2,将数据从内核拷贝到进程中 

阻塞与非阻塞可以简单理解为调用一个IO操作能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了;否则就可以理解为非阻塞。

阻塞I/O

当用户线程发起一个IO请求的时候,请求会到达内核,内核获取到数据后,将数据从内核空间拷贝到用户空间。期间,当内核未将数据准备好时,用户线程一直处于阻塞状态,CPU利用率不高。

为什么非得从内核空间拷贝到用户空间呢?

出于系统安全考虑,用户线程是没法直接读取内核态内存的。

非阻塞IO

当用户线程发起IO请求时,不用等到内核准备好数据才能返回,而是可以立刻返回,没有被阻塞住。但是用户线程始终还是得获取到数据,所以只能不断的轮询,检查内核空间的数据是否准备好,这样则很耗CPU。

IO多路复用

IO多路复用,其实是利用select函数阻塞多个IO操作,并对这些IO操作进行轮询检测,一旦数据准备好后,就可以通知线程进行真正的IO操作(此时数据已经在内核空间准备好了,此时用户线程直接进行拷贝的动作即可)。期间如果数据未准备好,用户线程可以可以干其他事情的。

JAVA NIO

JAVA NIO是非阻塞的,同时实现了IO多路复用。NIO中用户线程不会被读写操作阻塞住,它可以继续干事情,所以NIO是可以做到用一个线程来处理多个操作的。假设有10000个请求过来,根据实际情况,可以分配50或者100个线程来处理。不像之前的阻塞IO那样,非得分配10000个。

Selector 和 Channel
多个Channel以事件的方式可以注册到同一个Selector,从而达到用一个线程处理多个请求成为可能。

Channel
表示一个连接通道,连接的对象可以是文件、网络socket、硬盘。

Selector
一个组件,可以检测多个NIO channel,看看读或者写事件是否就绪。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java NIO(New I/O)是一个可以替代标准 Java I/O API 的 Java API。NIO 提供了更快速、更高效的 I/O 操作方式,也可以进行非阻塞 I/O 操作。 下面是几个 NIO 核心类和接口: - Buffer:缓冲区,用于数据的读取和写入。 - Channel:通道,用于数据的读取和写入。 - Selector:选择器,用于监控多个通道的 I/O 状态,从而实现多路复用。 下面介绍一下 NIO 的主要操作步骤: 1. 创建 Buffer 对象:创建一个 Buffer 对象,用于存储数据。 2. 创建 Channel 对象:创建一个 Channel 对象,用于读取和写入数据。 3. 打开 Channel:打开一个 Channel 对象,并连接到指定的服务器。 4. 将数据写入 Buffer:将需要写入的数据写入到 Buffer 中。 5. 切换 Buffer 模式:将 Buffer 从写模式切换到读模式。 6. 从 Buffer 中读取数据:从 Buffer 中读取数据。 7. 关闭 Channel:关闭 Channel 对象。 8. 关闭 Selector:关闭 Selector 对象。 下面是一个简单的 NIO 例子: ```java import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class NIOClient { public static void main(String[] args) throws IOException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("localhost", 8888)); ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put("Hello, server!".getBytes()); buffer.flip(); socketChannel.write(buffer); buffer.clear(); int num = socketChannel.read(buffer); System.out.println("Received from server: " + new String(buffer.array(), 0, num)); socketChannel.close(); } } ``` 这个例子中,我们先创建了一个 SocketChannel 对象,并连接到指定的服务器。然后,我们创建了一个 ByteBuffer 对象,将需要写入的数据写入到 ByteBuffer 中,切换 ByteBuffer 的模式,从中读取数据并输出到控制台,最后关闭 SocketChannel 对象。 希望这份简单的介绍能够帮助你更好的了解 Java NIO API。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值