Java知识总结(五)

JAVA BIO/NIO

同步

发起一个请求或任务,被调用者在未完成请求或任务前,不会返回结果。

需要一直等待该请求返回或任务完成反馈的结果,在这期间不能够去做其他的事情。

比如:你打电话给书店老板询问书籍,老板帮你去找书,你需要一直等待,等待书店老板给你回复。

异步

发起一个请求或任务之后,被调用者会理刻返回表示已经接受请求或任务,但是并没有返回结果,就接着去做别的事情,发出的请求或任务完成时,被调用者会返回结果。

比如:你打电话给书店老板询问书籍,你让他查到了再打电话给你,然后你挂断电话,期间你可以干其他事情,等到老本找到了书籍然后给你打电话。

阻塞

发起请求后,调用者需要一直等待结果返回,也就是当前的线程会被挂起,无法去做其他请求。

非阻塞

发起请求后,调用者不需要等待结果返回,可以去做别的事情。

BIO(Blocking I/O)(最传统的同步阻塞IO模型)

image-20210718153538501

典型的同步阻塞IO模型:data = socket.read();

当应用程序发出请求时,先去判断内核中的数据是否准备完成,如果没有准备完成,该应用程序就会被阻塞(让出cpu资源),等到内核数据准备完成,将数据拷贝给应用程序,应用程序解除block状态

基于字节流和字符流操作,数据流的特点是单向性,要么只读、要么只写。

server端要为每一个连接建立一个线程,这样的好处是每个线程可以专注自身的I/O操作并且编程简单。但是这种模型并不适合连接数过多情况。

NIO(Non - Blocking I/O)(同步非阻塞IO模型)

image-20210718154121553

当应用程序发出read请求后,不需要等待,它会马上得到来自内核的返回,如果返回的结果是error(数据没有准备好),那么应用程序就继续向内核发出请求,再次去确认,这样不停做循环,一旦内核准好数据同时应用程序发来请求,那么就将数据拷贝给应用程序,返回。

这样带来的问题:线程没有进入阻塞状态,它就不会让出cpu资源,导致cpu的占用率很高。

NIO的组成包括:Channel(通道)、 Buffer(缓冲区)、Selector

Channel

  • Channel和Stream()是同一个级别的,区别在于:Stream是单向的,而Channel是双向的,既可以用来读也可以用来写操作。

  • Channel的主要实现:

    1. FileChannel
    2. DatagramChannel
    3. SocketChannel
    4. ServerSocketChannel

    1对应文件IO、2对应文件UDP、3、4对应文件TCP(Server和 Client)

  • Buffer

    是一个容器,连续的数组用来存储数据。

    Channel提供从文件、网络读取数据的渠道,但是读写操作都必须由Buffer来操作。

    image-20210719154353391 image-20210719155137722

    上面是一个从客户端向服务器端发送数据的过程。

    客户端发出数据经过Buffer写入传给Channel,读入数据经过Channel将数据读入Buffer传给服务端。

  • Selector

    是NIO的核心类,通过Selector去检测多个Channel中是否有数据的发生(读或写请求),如果对应的Channel上有真正的请求发生,那么就去处理该Channel上的请求。Selector本身也是一个线程,设定一个线程专门去管理多个Channel的请求任务,而不需要为每一个Channel去建立对应的线程,避免了多个线程之间的上下文切换,大大减少了系统的开销。

    image-20210719160209617

多路复用IO模型

此模型的本质还是NIO模型,在NIO中的通过Selector实现在一个线程轮询多个通道的数据,需要先将用户线程中需要轮询的socket注册到Selector中,用Selector去轮询多个socketChannel是否有请求到达,一旦请求到达,Selector.select返回,最后完成I/O数据的传输这个过程用户线程是处于阻塞状态的。注意:socket配置也是非阻塞的。

image-20210719164029022

相比于NIO,多路复用IO用户线程首先需要在Reactor中注册一个事件处理器,然后Reactor(相当于上文提到的selector)负责轮询各个通道是否有新的数据到来,当有新的数据到来时,Reactor通过先前注册的事件处理器通知用户线程有数据可读,此时用户线程向内核发起读取IO数据的请求,用户线程阻塞直至数据读取完成。

image-20210719164038684

多路复用IO模型效率高于NIO模型原因在于:NIO中socket轮询是在用户线程中的,而多路复用是在内核中。

信号驱动IO模型

当用户线程发起一个I/O请求时,给对应的socket注册一个信号函数,用户不会立刻得到结果(内核中数据还没有准备好),而是继续去做别的事情,当内核中数据准备号时,给用户发送一个信号给用户线程,用户线程通过在信号函数中调用I/O操作进行实际的读写操作。

异步IO模型

该模型是最理想模型。它实现的流程:当用户线程发起read操作之后,就去做它自己的事情了,内核接收到用户线程的请求后,立刻返回,表明该请求已经受理,这个过程不会对用户线程造成任何阻塞。因为内核在完成数据准备后就将数据拷贝给用户线程,返回用户线程信息表明数据已经传输完毕,read操作已经完成,不需要用户线程再去调用IO操作。只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接去使用数据了。

和信号驱动模型的差别就在这里,信号驱动模型在内核完成数据准备之后,告诉用户线程数据已经准备完毕,需要你自己来调用IO操作拿到数据。


Java IO

img

IO分类

  • 按照流的流向分,可以分为输⼊流和输出流;
  • 按照操作单
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值