哦耶!冲进小米了!!!

文章分享了作者在小米公司Java后端的一二面面试经历,包括面向对象的基础知识、JVM垃圾回收器G1的讲解、线程池原理、SQL优化、链表算法等内容,以及个人的学习计划和面试感受。
摘要由CSDN通过智能技术生成

大家好,我是小阳。

分享一下自己上周六(2024.4.20)小米java后端一二面面经,已经拿到offer 。

整体流程记录:4月19号收到面试通知,20号下午两点面试,不到四个小时,就开始二面(没有任何思想准备,而且通知二面的时候,离面试开始只剩下八分钟就离谱,一面完就在刷手机了直接懵逼);接着进行了难熬的四天等待,太难熬了懂得都懂,最终25号上午收到offer,不管怎样还是要感谢小米🙏,给了我机会,春招到此结束开摆。

小米相比于互联网大厂面试难度是小了一点😊(被字节疯狂拷打自闭)。

小米一面

说一下面向对象的三大特征?

这个问题算是比较基础了,给面试官分别讲了封装、继承和多态;但是多态的话感觉讲的不是特别清楚,面试官一直追问,你觉着java为啥需要多态,我举出了自己使用栈时new Linkedlist<>();使用多态,简单说了比较灵活,但面试官似乎不太满意

面向对象的三大特征是封装、继承和多态。

1. 封装:封装是指将数据和操作数据的方法封装在一起,形成一个类。通过封装,类的内部细节对外部是隐藏的,只暴露必要的方法给外部访问,提高了安全性和可维护性。

2. 继承:继承是指一个类可以派生出子类,子类会继承父类的属性和方法。继承可以实现代码的重用,减少了代码量和复杂度,同时也提供了代码的组织和维护的便利性。

3. 多态:多态是指同一个方法可以在不同的对​​​​​​​象上呈现不同的行为。多态性可以通过继承和接口实现,使得代码可以根据实际对象的类型进行动态调用,提高了代码的灵活性和可扩展性。

总结:多态的理解还是不够深入,可以详细看看这篇博客java为啥需要多态​​​​​​​

jvm有哪些垃圾回收器?介绍一下特点​​​​​​​

常规八股,直接开始吟唱,这里详细介绍了G1收集器,一般记一个CMS和G1就够用了

我了解的有Serial收集器,Parallel收集器,Serial old ,CMS, G1收集器;对G1收集器比较熟悉,开创了收集器面向局部收集的设计思路和基于 Region 的内存布局,主要面向服务端,最初设计目标是替换CMS。

G1之前的收集器,垃圾收集目标要么是整个新生代,要么是整个老年代或整个堆。而G1可面向堆任何部分来组成回收集进行回收,衡量标准不再是分代,而是哪块内存中存放的垃圾数量最多,回收受益最大。

跟踪各Region里垃圾的价值,价值即回收所获空间大小以及回收所需时间的经验值,在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间优先处理回收价值最大的Region,这种方式保证了G1在有限时间内获取尽可能高的收集效率。

G1 运作过程:

  • 初始标记:标记GC Roots能直接关联到的对象,让下一阶段用户线程并发运行时能正确地在可用Region中分配新对象。需要STW但耗时很短,在Minor GC 时同步完成。
  • 并发标记:从GC Roots开始对堆中对象进行可达性分析,递归扫描整个堆的对象图。耗时长但可与用户线程并发,扫描完成后要重新处理SATB记录的在并发时有变动的对象。
  • 最终标记:对用户线程做短暂暂停,处理并发阶段结束后仍遗留下来的少量SATB记录。
  • 筛选回收:对各Region的回收价值[排序](),根据用户期望停顿时间制定回收计划。必须暂停用户线程,由多条收集线程并行完成。

可由用户指定期望停顿时间是 G1的一个强大功能,但该值不能设得太低,一般设置为100~300 ms。

追问:OK,你刚才提到有个并发标记,然后还有一个初始标记,那为什么进行并发标记前要先进行初始标记?

问到这个,是有点懵的,想看你是不是死背的八股。这个当时虽然不会,但你也要思考,不能啥也不说,我当时就是凭感觉就说,初始标记是为了判断有没有存活对象,如果没有就不进行并发标记了,就说我是这么想的不一定正确;虽然说得不对,但是要展现你的思考过程

进行并发标记前进行初始标记的目的是为了在并发标记阶段准确地确定哪些对象是存活的。

在并发标记开始时,GC Roots能直接关联到的对象已经被标记为存活。初始标记的作用是标记那些在GC Roots直接可达的对象,并将其标记为存活。这样,在并发标记阶段可以正确地对整个堆进行可达性分析,确定哪些对象是存活的,哪些对象可以被回收。进行初始标记时需要进行短暂的STW停顿,但由于只标记部分对象,所以耗时很短。而并发标记阶段是在用户线程并发运行时进行的,可以对堆中的对象进行全面的扫描和标记,耗时较长。

因此,初始标记的目的是为了保证并发标记阶段的准确性和效率。

可以简单谈一下java线程池的一些原理吗?它是怎么工作的?

提交一个任务到线程池中,线程池的处理流程如下:


1.判断线程池里的核心线程数是否已满,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程数已满,则进入下个流程。
2.线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3.判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

追问:如果说我在这个线程数没有到达核心线程数之前,那我往这个线程池里面提交多次任务的话,它的线程会有复用吗?

还是你考察是否真正理解线程池,这里我当时给他做了分析,说核心线程创建了不会被销毁,但是普通线程会被销毁。之前看过一个有意思的比喻,就是核心线程就是正式员工可以长期干,普通线程就是外包,完成这个项目就可以走了。

是的,线程池在没有达到核心线程数之前,会尽可能地重用现有的线程来处理提交的多个任务。这意味着如果在这个阈值之前多次提交任务,线程池会尽量利用已经存在的线程来执行这些任务,而不是每次都创建新的线程。这种重用线程的机制有助于提高线程池的性能和效率,因为避免了频繁地创建和销毁线程所带来的开销。

Myqsl这一块,然后说有一个慢查询,可以简单一下你的一个优化思路是什么样子吗?

对这一块回答,感觉面试官比较满意,看见他点头了

当时回答是,首先要开起慢查询日志,找到慢sql语句。如果没用索引的话,看查询语句是否是select * 查找,我们可以改成具体的字段提高性能;

如果用了索引,在sql语句前加上explain查看type字段是否为index或all,如果是就代表没有走索引,然后就给他分析索引失效的几种情况

  • 如果是联合索引的话是否符合最左匹配原则
  • 是否对索引字段进行了运算,导致索引失效
  • 索引设计不合理,区分度不大,优化器选择了全局搜索,比如用性别字段做索引

然后分析了几种解决办法,

  • 考虑重新设计索引字段
  • 用上覆盖索引和索引下推,减少回表次数
  • 避免使用函数运算
  • 建立联合索引

追问:如果说命中了索引,你觉得可能还有啥其他原因

这个一开始答错了,我说了可能是建立区分度不大字段索引,比如性别,然后说了一半,又想到那个优化器会直接全表扫描,就不走索引,意识到说错了😅  然后就想到了分表,答得太着急了

如果命中了索引,那么可能就是单表的数据量太大了,一般单表超过500w就要进行分表操作

如果是排序的话,你知道排序里面的最左匹配原则那个东西吗?

假设有一个(a, b, c)联合索引,它的存储顺序是先按a排序,在a相同的情况再按b排序,在b相同的情况再按c排序。由于这个的特性,在使用联合索引时,存在最左匹配原则,具体的规则:

  • MySQL 会从联合索引从最左边的索引列开始匹配查询条件,然后依次从从左到右的顺序匹配,如果查询条件没有使用到某个列,那么该列右边的所有列都无法使用走索引。
  • 当查询条件中使用了某个列,但是该列的值包含范围查询,范围查询的字段可以用到联合索引,但是在范围查询字段的后面的字段无法用到联合索引。

追问:什么情况下匹配会中断?

这里举出了例子,比如建立(a,b,c)索引,然后有一个查询a=?and c=? 那么的话a会走索引,c不能走索引

追问:那么如果你这个例子,是查询a=? and b 在in里面,and c=?b会走索引吗?

这里答错了,对联合索引失效了解的就最基本的失效,还知道一个范围查询的情况;还得加强,推荐大家看小林coding里面讲得非常清楚关于这一块

这里b不会走索引

Mysql连接池是什么?它的工作原理是什么?

这里有点尴尬,没看到过这个,虽然自己在项目也用到过了,没看过八股。就这自己的理解和线程池类比介绍了一下,回答得不是很全面。期间沉默了几秒,都没说话,我觉着我说完了,但是他好像还在等我继续往下说,沉默了几秒要窒息了;这个答得不好😅

MySQL连接池是一种用于管理和重用数据库连接的技术,它可以在应用程序和数据库之间建立一组预先创建的数据库连接,并将这些连接存储在一个池中,供应用程序从中获取和归还。

MySQL连接池的工作原理如下:

  1. 初始化连接池:在应用程序启动时,连接池会根据配置参数初始化一定数量的数据库连接,并将这些连接存放在一个池中。
  2. 获取连接:当应用程序需要与数据库交互时,它可以从连接池中获取一个可用的连接。连接池会维护一个连接状态的列表,记录哪些连接是空闲的可用的。应用程序通过获得一个可用连接,可以避免每次都去创建新的数据库连接,从而减少了连接的创建和销毁的开销。
  3. 使用连接:应用程序通过获取到的连接来执行数据库操作,如查询、插入或更新数据。
  4.  归还连接:当应用程序完成对数据库的操作后,会将连接归还给连接池,以便其他线程或请求可以继续使用该连接。
  5.  连接回收:连接池会定期检查连接的状态,如果连接长时间没有被使用,连接池会自动将其关闭并回收资源。同时,连接池也会根据配置的最小和最大连接数来动态调整连接的数量,以适应应用程序的需求。

通过使用连接池,可以减少数据库连接的创建和销毁次数,提高了数据库访问的性能和效率。同时,连接池还能够控制并发连接数,避免过多的连接对数据库造成负荷,提高系统的稳定性。

说一下键入网址的过程?

在浏览器输入网址后:

  1. 浏览器会先解析 URL,解析出域名、资源路径、端口等信息,然后构造HTTP 请求报文。
  2. 接着进行域名解析,将域名解析为 IP地址,会先查系统缓存是否域名信息,如果有就返回IP 地址,没有就会查看本地系统 host 文件有没有域名信息,如果有就返回IP 地址,如果没有就去查本地 DNS 服务器,如果本地 DNS 服务器缓存中有域名信息,就返回 IP 地址,否则本地DNS服务器分别去根域名服务器->顶级域名服务器->权威域名服务器询问,最后拿着返回的IP交给浏览器。
  3. 由于HTTP是基于TCP传输的,所以在发送HTTP请求前,需要进行三次握手,在客户端发送第一次握手的时候,TCP头部会填上SYN标记位,同时填上目标端口和源端口的信息。源端口是浏览器随机生成的,目标端口要看是HTTP还是HTTPS,如果是 HTTP 默认目标端口是 80,如果是HTTPS 默认是 443
  4. 然后到网络层,会加上IP头,同时填上目标IP地址和源IP地址。
  5. 然后到数据链路层,会通过ARP协议,获取路由器的MAC地址,然后会加上MAC头,填上目标MAC地址和源MAC地址。
  6. 然后到物理层之后,直接把数据包,转发给路由器,路由器再通过下一跳,最终找到目标服务器,然后目标服务器收到客户的SYN报文后,会响应第二次握手。
  7. 当双方都完成三次握手后,如果是HTTP协议,客户端就会将HTTP请求就会发送给目标服务器;如果是HTTPS协议,客户端还要和服务端进行TLS四次握手之后,客户端才会将HTTP报文发送给目标服务器。
  8. 目标服务器收到HTTP请求消息后,就返回HTTP响应消息,浏览器会对响应消息进行解析渲染,呈现给用户。

以上就是输入网址之后,期间发生的事情。

平常在学校有没有给自己制定一些学习计划,去提升自己能力?

录音:有的,我现在也会制定一些计划,比如说我就是要做什么,然后想想一些想一些技术需要提
高。比如说我就在最近在学那个啥消息队列,然后我这个消息队列掌握的感觉还是不是也挺
复杂的,感觉也不是现在就在想学习这个消息队列,还有一些还有一些那种设计模式,这方
面这两方面我是不太熟悉的。然后的话再再进行学习提高。最近也有在写那个博客,做一些
那种文章的分享之类的,然后就想着学习,然后提高自己。

算法题

特别简单,就是判断一个数字是不是回文数字,不到三分钟直接秒了

反问环节

说了一下感觉自己回答不太好,然后面试官说实习的话已经不错了,一些赞赏的话结束

总结

面试体验是不错的,人很好也没有为难,可能是前面回答的不错,算法没有为难我😅

小米二面

手撕算法

1. 反转链表 2.判断链表是否有环;直接秒了,都是力扣原题属实不难,白刷二百道了都没考😂

leetcode-反转链表

leetcode-判断链表是否有环

项目

基本没问八股,项目聊得挺深,还好有准备

聊天

对小米认识?

现在是否有offer?

怎么学习新知识?

总结

二面的面试官非常好,上来先自我介绍,人很礼貌,体验感很好。

还是要感谢小米🙏,给我这次机会,整体难度不大,真的不容易,结束春招开始摆烂🙂‍↔️

  • 38
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值