Java教程

打卡面试题-day06(javaSE)

本文主要是介绍打卡面试题-day06(javaSE),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

IO

什么是BIO

BIO就是传统的java.io包,是基于流模型实现的,交互的方式是同步,阻塞方式,也就是读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,他们之间的调用是可靠的线性顺序,优点:代码比较简单,直观;缺点:IO的效率和扩展性很低,容易成为应用型瓶颈。

什么是NIO

是java1.4引入的java.nio包,提供了Channel,Selector,Buffer等新的抽象,可以构建多路复用的,同步非阻塞IO程序,同时提供了更接近操作系统底层高性能的数据操作方式。

什么是AIO

AIO是java1.7之后引入的包,是NIO的升级版本,提供了异步非阻塞的IO操作方式,所以人们叫它AIO(Asychronous IO),异步IO是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会阻塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

同步与异步

同步
就是一个任务的完成需要依赖另外一个任务时,只用等待被依赖的任务完成后,以来的任务才能算完成,是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。
异步
不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务是否真正完成,依赖它的任务无法确定,所以他是不可能的任务序列。
可以用打电话和发短信来比喻

阻塞与非阻塞

阻塞与非阻塞主要是从CPU的消耗来说
阻塞就是CPU停下来等待一个慢的操作完成,CPU才接着完成其他的事。
非阻塞就是在这个慢的操作在执行时CPU去干其他别的事,等这个慢的操作完成时,CPU再接着完成后续的操作。
虽然表面上上非阻塞的方式可以明显的提高CPU的利用率,但是也带来的另一种后果就是系统的线程切换增加。增加的了CPU使用时间能不能补偿的切换成本需要好好评估。

同步、异步、阻塞、非阻塞

组合方式性能分析
同步阻塞最常用的一种用法,使用也是最简单的,但是IO性能一般很差,CPU大部分时间处在空闲时间
同步非阻塞提升IO性能的常用手段,就是将IO的阻塞改成非阻塞方式,尤其在网络IO是长连接,同时传输数据也不是很多的情况下,提升性能非常有效,这种方式通常能提升IO性能,但是会增加CPU消耗,要考虑增加的IO性能能不能补偿CPU的消耗,也就是系统的瓶颈是在IO还是在CPU上
异步阻塞该方法在分布式数据库中经常用到,例如在往一个分布式数据库中添加一条记录,通常会有一份是同步阻塞的记录,而还有两至三份是备份记录会写到其他机器上,这些备份记录通常都是采用异步阻塞的方式写IO。异步阻塞对网络IO能够提升效率,尤其像上面同时写多份相同的数据的情况
异步非阻塞用起来比较复杂,只有在一些非常复杂的分布式情况下使用,像集群之间的消息同步机制一般用这种IO组合方式。如Cassandra的Gossip通信机制就是采用异步非阻塞的方式。它适合同时要传多份相同的数据到集群中不同的机器,同时数据的传输量虽然不大,但是却非常频繁。这种网络IO用这个方式性能能达到最高。

通道是什么意思

通道是对原IO包中的流的模拟。到任何目的地的所有数据都必须通过一个Charnnel对象(通道)。一个Buffer实质上是一个容器对象。发送给一个通道的所有对象都必须放到缓冲区中,同样,从通道中读取的任何数据都要读到缓冲区。Channel是一个对象,通过它可以读取和写入数据。拿NIO与原来的IO做个比较,通道就是一个流。
正如前面提到的,所有数据都通过Buffer对象来处理,永远不会直接写入通道中,相反,而是将数据写入包含一个或多个字节的缓冲区。同样,也不会从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

缓冲区是什么意思

Buffer是一个对象,它包含一些要写入或者刚读出的数据。在NIO中加入Buffer对象,体现了新库与原IO的一个重要区别。在面向流的IO中,将数据直接写入或者将数据直接读到Stream对象中。
在NIO库中,所有的数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问NIO中的数据,都是将它放到缓冲区中。
缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不仅仅是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读写进程。

IO多路复用的底层原理

IO多路使用两个系统调用(select/poll/epoll和recvfrom),blocking IO 只调用了recvfrom;select/poll/epoll核心是可以同时处理多个connection,而不是更快,所以连接不高的话,性能不一定比多线程+阻塞IO好,多路复用模型中,每一个socket,设置为non-blocking,阻塞是被select这个函数block,而不是被socket阻塞的。
select机制
客户端操作服务器时就会产生这三种文件描述符(简称fd):writerfds(写),readfds(读),exceptfds(异常)。select会阻塞住监听3类文件描述符,等有数据,可读,可写,出异常或超时,就会返回;返回后通过遍历fdest整个数组来找到就绪的描述符fd,然后进行对应的IO操作。
优点:几乎在所有的平台上支持,跨平台支持性好
缺点:由于采用轮训全盘扫描,会随着文件描述FD数量增多而性能下降。
每次调用select(),需要把fd集合从用户态拷贝到内存态,并进行遍历(消息传递都是从内核到用户空间)
默认单个进程打开的FD有限制1024个,可修改宏定义,但是效率仍然慢。
poll机制
epoll之所以高性能得益于它的三个函数
epoll_create()系统启动时,在Linux内核里面申请一个B+树结构文件系统,返回epoll对象,也是一个fd
epoll_ctl()每新建一个连接。都通过该函数操作epoll对象,在这个对象里面修改添加删除对应的链接fd,绑定一个callback函数。
epoll_wait()轮训所有的callback集合,并完成相应的IO操作。
优点:没fd这个限制,所支持的fd上限是操作系统的最大文件句柄数,1G内存大概支持10万个句柄。
效率提高,使用回调通知而不是轮询的方式,不会随着fd数目的增加效率下降。
内存和用户空mmap同一块内存实现。

这篇关于打卡面试题-day06(javaSE)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!