来聊一聊Java的BIO和NIO及一些底层原理,有时间下期更新Netty相关内容~
模型基本说明
- 什么是I/O模型:就是用什么样的通道进行数据发送和接收,很大程度上决定了程序通信的性能
- Java共支持3种网络编程模型I/O模式: BIO、NIO、AIO传统Java的I/O模型
BIO:同步并阻塞(传统阻塞型)
- 服务器为每一个新连接建立一个 新线程 进行处理,如果连接没有数据也会 阻塞等待 (不做任何事情)造成不必要的线程开销(示意图如下) PS:BIO -> blocking io
现在Java的I/O模型
NIO:同步非阻塞
- 服务器的一个线程能处理多个请求(连接),客户端发送的连接请求会注册到多路复用器上,多路复用器轮询到连接有I/O请求就进行处理(示意图如下) PS:NIO -> non-blocking io
AIO:异步非阻塞(非重点)
- 引入了异步通道的概念,采用Proactor模式,简化了程序编写,有效的请求才会启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时长较长的应用BIO、NIO、AIO使用场景分析
- BIO适用于连接数小且固定的架构,对服务器资源占用高,一般只在JDK1.4以前(唯一选择)
- NIO适用于连接数目多且连接比较短的架构,如聊天服务器,弹幕系统,编程复杂,JDK1.4开始才有
- AIO适用于连接数目多且连接比较长的架构,如相册服务器,充分调用OS参与并发操作,JDK1.7后出现Java BIO 编程BIO基本介绍
- Java BIO就是传统的Java I/O编程,其相关类和接口在 java.io
- BIO(Blocking IO):同步阻塞,服务器为每个连接请求建立新的线程,如果没有事情做也会阻塞等待,直到断开链接,这样会造成 不必要的线程开销
- 对于BIO的架构可以通过线程池机制改善(多个客户连接服务器)
- BIO 占用资源高 ,适用于连接数比较小且固定的架构,但是代码简单Java BIO 工作机制
BIO工作流程
- 服务端启动一个 ServerSocket
- 客户端启动 Socket 对服务器进行通信,服务器对每一个客户端线程之间建立通讯
- 客户端线程请求结束后,断开链接,服务端线程结束Java BIO问题分析
- 每个请求都需要创建独立的线程,为客户端数据Read/Write
- 当并发数大的时候,要创建大量线程来处理链接,系统资源占用大
- 建立连接后,线程如果暂时没有数据可读,就阻塞在Read上,造成线程资源浪费Java NIO 编程NIO基本介绍
- Java NIO 全称 Java non-blocking IO 是JDK1.4开始提供的新API,是 同步非阻塞 的
- NIO相关类都放在java.nio包下,并对原 java.io 包中的很多类进行改写
- NIO有三大核心部分: Channel(通道)、Buffer(缓冲区)、Selector(选择器)
- NIO是 面向缓冲区,或者面向块编程 的,不是简单的read和write,数据读取到一个它稍后处理的缓冲区,也可按需要在缓冲区前后移动读取数据
- NIO的 非阻塞模式 :一个线程从某通道读取数据的时候, 仅能得到目前可用的数据 ,当没有可用的数据时,什么都不会获取,会去做别的事情( 因为数据是块的,所以等它攒到一定大小直到可用的时候再给就行,而不会因为数据是散装的要一直阻塞等待浪费线程!!! )
- 这样就能将很多请求交由一个线程处理,大幅度减少线程开销NIO和BIO
- BIO以 流 的形式处理数据,NIO以 块 的形式处理数据
- BIO是 阻塞的 ,NIO是 非阻塞的
- BIO的流是 字节流 和 字符流 , 而NIO的块基于 Channel(通道) 和 Buffer(缓冲区) 读取数据 , Selector(选择器) 监听多个通道的 事件(连接请求,数据到达)NIO三大核心关系图
- 每一个Channel都会对应一个Buffer
- Selector对应一个服务器线程,一个线程对应多个Channel
- Selector选择哪个是由Channel的 事件Event 决定的
- Selector会根据事件安排在各个通道上 切换
- Buffer是缓冲区,其实就是一个内存块,底层就是一个数组(bytebuffer)
- Buffer的读写是双向,既可以读也可以写,像底层操作系统的系统通道也是双向的缓冲区(Buffer)
Buffer的本质 -> 可以读写的数据内存块(容器对象)
数据的读写必须经过buffer
Buffer类的基本信息
Buffer类相关方法(比较灵活)
通道(Channel)
NIO通道与BIO的流的区别
- 通道可以同时进行读写,流只能读或者写
- 通道可以异步读写数据,流只能同步
- 通道可以从缓冲区读&写数据
常用Channel类
- BIO的Stream是 单向 的,NIO的Channel是 双向 的
- 常用的Channel类: ServerSocketChannel (类似ServerSocket)和 SocketChannel (类似Socket)
- Filechannel ->文件读写通道
- DatagramChannel -> UDP数据读写通道
- ServerSocketChannel & SocketChannel -> TCP读写通道
Selector(选择器)
- Java的NIO,用非阻塞IO模式,得益于 Selector
- 多个Channel以事件的方式注册到同一个Selector -> 这样Selector可监控多个通道是否有事件发生 -> 一个线程管理多个通道的连接和请求
- 只有有事件发生时才回去读写,减少线程开销(线程上下文切换)
- 线程在非阻塞IO的空闲时间在其他有需要的通道上执行IO操作,节约了时间
- Netty的IO线程NioEventLoop(事件)
网友评论