IO、BIO、NIO、AIO

1、基础知识点

1.1、同步与异步

        关注的是被调用方的执行方式及返回时机
        同步:被调用方做完内部所有事情后再返回,同步调用的调用者一定会得到被调用方的结果。
        异步:被调用方先返回,再做事情,做完所有事情后再通知调用方(回调方法),异步调用方不会立即得到被调用方的结果,而是当被调用方执行完成后通过回调函数处理该结果。

1.2、阻塞与非阻塞

        关注的是调用方在被调用方返回结果之前的这段时间,是否处于等待状态
        阻塞:调用方在等待被调用方返回结果的这段时间什么都不干;
        非阻塞:调用方在等待被调用方返回结果的这段时间去处理其他事情。

1.3.同步/异步与阻塞/非阻塞对比

        同步/异步从行为角度描述事物,针对的对象是被调用方,主要关注被调用方的执行方式及返回时机。
        阻塞/非阻塞描述当前事物的状态(等待调用结果时的状态),针对的对象是调用方,主要关注调用方是否在等待被调用方返回结果的这段时间是否处于等待状态。

1.4、并发与并行

        并发:一个时间段内,几个程序都在同一个CPU上运行,但任意一个时刻点上只有一个程序在处理机上运行。
        并行:一个时间段内,几个程序在不同的CPU上运行,任意一个时刻点上,有多个程序在同时运行,并且多道程序之间互不干扰。

2、I/O

        I/O是Input输入/Output输出的简称,通常指数据在内部存储器(内存外部存储器(硬盘、优盘或其他周边设备之间的输入和输出。
  输入/输出是信息处理系统(计算机)与外部世界(人类或另一信息处理系统)之间的通信。

3、BIO 

       BIO (blocking-io,同步阻塞I/O)模式,数据的读取写入必须阻塞在一个线程内等待其完成。

3.1、BIO通信模型:一请求一应答

        采用BIO通信模型的服务端,一般由一个独立的Acceptor线程负责监听客户端的连接,一般通过while(true)循环中服务端会调用accept()方法等待接收客户端的连接的方式监听请求;一旦接收到一个客户端的连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时当前线程不能再接收其他客户端连接请求,只能等待当前客户端的操作执行完成(可通过多线程来支持多个客户端的连接)
   一请求一应答通信模型:服务端接收到客户端连接请求后为每个客户端创建一个新的线程进行链路处理,处理完成后,通过输出流返回应答给客户端,线程销毁。
   客户端并发访问量增加后一请求一应答模型的弊端:若连接不做任何事情就会造成不必要的线程开销,在Java虚拟机中,线程是宝贵的资源,线程的创建、销毁、切换成本很高,如果并发量增加会导致线程数急剧膨胀可能会导致线程堆栈溢出、创建新线程失败等问题,最终导致服务端不能对外提供服务。

socket流程图:   ​​​​​​​

 

        解决一请求一应答模型的弊端,后端通过一个线程池来处理多个客户端的请求接入,形成客户端个数M:线程池最大线程数N的比例关系,M可以远大于N,通过线程池就可以灵活的调配线程资源,避免每个请求都创建一个独立线程造成的线程资源耗尽,并设置线程池最大值,防止由于海量并发接入导致线程耗尽。
        当活动连接数不是特别高(小于1000),BIO模型比较实用,每个连接专注于自己的I/O且编程模型简单,线程池本身是个天然的漏斗,可以缓冲一些系统处理不了的连接或请求,当若面对上百万级连接时,BIO无能为力。

4、NIO(New I/O,Non-Block I/O)

        同步非阻塞的I/O模型,支持面向缓冲的,基于通道的I/O操作方法,提供SocketChannel和ServerSocketChannel并支持阻塞(与BIO一样)与非阻塞两种模式。对于低负载、低并发的应用程序可以使用同步阻塞I/O提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用使用NIO的非阻塞模式。

        jdk提供的nio的代码在:java.nio包下。

4.1、IO与NIO区别

4.1.1、IO流是阻塞的,NIO的非阻塞的

        IO:IO各种流是阻塞的,当线程调用read()或write()时,该线程被阻塞,直到一些数据被读取或数据完全写入,该线程在此期间不能再干任何事情了。
        NIO:NIO可以进行非阻塞IO操作,比如:单线程从通道读取数据到buffer,同时继续做别的事情,当数据读取到buffer后,线程再继续处理数据。写数据也是一样的,一个线程请求写入一些数据到某通道,不需要等待它完全写入,这个线程同时可以去做别的事情。

4.1.2、IO是面向流的,NIO是面向缓冲区的

        IO:面向流的IO可以将数据直接写入或将数据直接读到Stream对象中。
        NIO:NIO直接读到Buffer中进行操作,所有数据都是用缓冲区处理的,读取数据是直接读到缓冲区,写入数据也是直接写入到缓冲区,任何时候访问NIO中的数据,都是通过缓冲区进行操作。

NIO通过Channel(通道)进行读写
    Channel通道是双向的,可读也可写,而流是单向的。无论读写,通道只能与Buffer交互,通道可以异步的读写。

4.2、NIO有Selector选择器

        Selector选择器用于使用单个线程处理多个通道,只需要较少的线程来处理这些通道,线程之间切换对于操作系统来讲是昂贵的,因此选择器会提高系统效率。
        Thread->Selector->Channel1/Channel2/Channel3

NIO(多selector)模型图:

4.3、NIO读写数据方式

        NIO中所有的IO都是从Channel(通道)就开始的
        从通道进行数据读取:创建一个缓冲区,然后请求通道读取数据->(Channel->Buffer)
        从通道进行数据写入:创建一个缓冲区,填充数据,并要求通道写入数据->(Buffer->Channel)

4.4、nio的几个概念

4.4.1、Channel:

        Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流,而且他们面向缓冲区的。

        所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

        通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而 通道 可以用于读、写或者同时用于读写。

        因为它们是双向的,所以通道可以比流更好地反映底层操作系统的真实情况。特别是在 UNIX 模型中,底层操作系统通道是双向的。

4.4.2、缓冲区:

        缓冲区 是一个固定数据量的指定基本类型的数据容器。除内容之外,缓冲区还具有位置 和界限,其中位置是要读写的下一个元素的索引,界限是第一个应该读写的元素的索引。基本 Buffer 类定义了这些属性以及清除、反转 和重绕 方法,用以标记 当前位置,以及将当前位置重置 为前一个标记处。

        每个非布尔基本类型都有一个缓冲区类。每个类定义了一系列用于将数据移出或移入缓冲区的 get 和 put 方法,用于压缩、复制 和切片 缓冲区的方法,以及用于分的异类或同类二进制数据序列),访问要么是以 big-endian字节顺序进行,要么是以 little-endian 字节顺序进行。

5、AIO

        AIO是异步IO,在读取数据的整个过程都是异步的,当数据准备好之后,直接由操作系统内核缓冲区将数据复制到用户缓冲区,整个过程不需要用户线程做什么。
        但AIO现在还没有广泛应用,现在的大公司服务端采用的都是多路复用IO模型(NIO),特点是支持高并发。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值