IO基础知识

IO类型:

Java BIO同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销
Java NIO同步非阻塞服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求就进行处理
Java AIO(NIO.2)异步非阻塞,AIO 引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用

IO使用场景分析

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序简单易理解。
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4开始支持。
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

什么是同步和异步?什么是阻塞和非阻塞?

首先要知道,同步和异步是针对调用方,阻塞与非阻塞是针对被调用方的。

同步与异步:对于调用方来讲调用一个方法是否需要等待调用方法的返回结果就是同步和异步的区别。如果需要等待函数的返回就是同步,不等待则是异步。
调用者主动等待调用的结果,那么就是同步。如果是被调用者主动去通知调用者,就是异步。
阻塞与非阻塞:对于被调用方来说,当被调用方调用时是否立即返回结果就是阻塞与非阻塞的区别。如果被调用方立即返回结果就是非阻塞的,反之如果需要等待处理过程结束后才返回结果就是阻塞的。阻塞是指I/O操作需要彻底完成后才能返回用户空间。非阻塞是指I/O操作被调用后立即返回一个状态值,无需等I/O操作彻底完成。

同步阻塞。当执行者要执行由A-B-C三件事情组成的DEMO,当A执行完之后调用B,B执行完成之后在调用C,最终此事件完成。这种A执行完之后调用下一件事的动作就是同步。而执行者等待这个DEMO的完成的动作则是阻塞。

而什么是同步非阻塞呢?总事物还是按照原计划执行,但是执行者会在DEMO完成期间去做别的事件,但是它会监听此DEMO是否执行完成。如果完成,又会切换回来完成之后的事件。切换的动作就是非阻塞了。

说完前两个,肯定要说说异步非阻塞了。异步与同步的区别在于,同步切换的动作是当执行者监听到DEMO完成,再切换。而异步则是当DEMO完成之后会发出完成的广播,通知执行者,然后执行者按照自己的计划去切换。

在这里插入图片描述
将三个IO操作都注册到Selector中去,当有IO操作发生,给Selector发送消息。当选择器接收到请求,就会根据相应逻辑分配线程去处理。

NIO 和 BIO 的比较

BIO 以流的方式处理数据,而 NIO 以块的方式处理数据,块 I/O 的效率比流 I/O 高很多

BIO 是阻塞的,NIO 则是非阻塞的

BIO基于字节流和字符流进行操作,而 NIO 基于 Channel(通道)和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择器)用于监听多个通道的事件(比如:连接请求,数据到达等),因此使用单个线程就可以监听多个客户端通道

NIO详解

NIO:同步非阻塞式IO

NIO:
Buffer、Channel、SelectionKey、Selector、事件
NIO 有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)

NIO是 面向缓冲区 ,或者面向 编程的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络

Java NIO的非阻塞模式,使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。

通俗理解:NIO是可以做到用一个线程来处理多个操作的。假设有10000个请求过来,根据实际情况,可以分配50或者100个线程来处理。不像之前的阻塞IO那样,非得分配10000个。

Buffer:
缓存数组,就是一个内存块,底层用数组实现
与Channel进行数据的读写。
数据的读取写入是通过Buffer, 这个和BIO 一样, 而BIO 中要么是输入流,或者是输出流, 不能双向,但是NIO的Buffer 是可以读也可以写, 需要 flip 方法切换。

Channel:
通信通道,每个客户端连接都会建立一个Channel通道

我的理解是:客户端直接与Channel进行通信,当客户端发送消息时,消息就流通到Channel里面,本地程序需要将Channel里面的数据存放在Buffer里面,才可以查看;当本地需要发送消息时,先把消息存在Buffer里面,再将Buffer里面的数据放入Channel,数据就流通到了客户端

总而言之:Buffer就是本地程序与Channel数据交换的一个中间媒介。
在这里插入图片描述

SelectionKey、Selector:

Selector:Selector通过管理SelectionKey的集合从而去监听各个Channel。当Channel注册到Selector上面时,会携带该Channel关注的事件(SelectionKey包含Channel以及与之对应的事件),并会返回一个SelectionKey的对象,Selector将该对象加入到它统一管理的集合中去,从而对Channel进行管理
Selector能够检测多个注册的通道上是否有事件发生(注意:多个Channel以事件的方式可以注册到同一个Selector)

NIO之所以是非阻塞的,关键在于它一个线程可以同时处理多个客户端的通信。而Selector就是它一个线程如何处理多个客户端通信的关键,一个Selector就对应一个线程

首先在创建与客户端连接的Channel时,应该调用 Channel.register()方法,将Channel注册到一个Selector上面。调用该方法后,会返回一个SelectionKey对象,该对象与Channel是一一对应的。而Selector则通过管理SelectionKey的集合间接的去管理各个Channel。示例图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值