前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【面试进行时】大厂常考面试题一览(一)

【面试进行时】大厂常考面试题一览(一)

作者头像
南橘
发布2021-04-02 11:41:32
3350
发布2021-04-02 11:41:32
举报
文章被收录于专栏:进阶之路

.markdown-body{word-break:break-word;line-height:1.75;font-weight:400;font-size:15px;overflow-x:hidden;color:#333}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{line-height:1.5;margin-top:35px;margin-bottom:10px;padding-bottom:5px}.markdown-body h1{font-size:30px;margin-bottom:5px}.markdown-body h2{padding-bottom:12px;font-size:24px;border-bottom:1px solid #ececec}.markdown-body h3{font-size:18px;padding-bottom:0}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:15px}.markdown-body h6{margin-top:5px}.markdown-body p{line-height:inherit;margin-top:22px;margin-bottom:22px}.markdown-body img{max-width:100%}.markdown-body hr{border:none;border-top:1px solid #ddd;margin-top:32px;margin-bottom:32px}.markdown-body code{word-break:break-word;border-radius:2px;overflow-x:auto;background-color:#fff5f5;color:#ff502c;font-size:.87em;padding:.065em .4em}.markdown-body code,.markdown-body pre{font-family:Menlo,Monaco,Consolas,Courier New,monospace}.markdown-body pre{overflow:auto;position:relative;line-height:1.75}.markdown-body pre>code{font-size:12px;padding:15px 12px;margin:0;word-break:normal;display:block;overflow-x:auto;color:#333;background:#f8f8f8}.markdown-body a{text-decoration:none;color:#0269c8;border-bottom:1px solid #d1e9ff}.markdown-body a:active,.markdown-body a:hover{color:#275b8c}.markdown-body table{display:inline-block!important;font-size:12px;width:auto;max-width:100%;overflow:auto;border:1px solid #f6f6f6}.markdown-body thead{background:#f6f6f6;color:#000;text-align:left}.markdown-body tr:nth-child(2n){background-color:#fcfcfc}.markdown-body td,.markdown-body th{padding:12px 7px;line-height:24px}.markdown-body td{min-width:120px}.markdown-body blockquote{color:#666;padding:1px 23px;margin:22px 0;border-left:4px solid #cbcbcb;background-color:#f8f8f8}.markdown-body blockquote:after{display:block;content:""}.markdown-body blockquote>p{margin:10px 0}.markdown-body ol,.markdown-body ul{padding-left:28px}.markdown-body ol li,.markdown-body ul li{margin-bottom:0;list-style:inherit}.markdown-body ol li .task-list-item,.markdown-body ul li .task-list-item{list-style:none}.markdown-body ol li .task-list-item ol,.markdown-body ol li .task-list-item ul,.markdown-body ul li .task-list-item ol,.markdown-body ul li .task-list-item ul{margin-top:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:3px}.markdown-body ol li{padding-left:6px}.markdown-body .contains-task-list{padding-left:0}.markdown-body .task-list-item{list-style:none}@media (max-width:720px){.markdown-body h1{font-size:24px}.markdown-body h2{font-size:20px}.markdown-body h3{font-size:18px}}

这几天在整理之前的面试资料,又偶在在群里和各位同学一起探讨些奇妙的问题,心有所感,便准备将这些题目整理起来,一来是分析给大家,二来也以备日后之需。

一面二面主要是基础面,问的都是一些基础知识,难度不是很高,这里我就简单的分享一下我所遇到的题目。

一、面试者你好,我们开门见山,能跟我介绍一下spring的核心特征吗?包括Spring bean的生命周期也可以讲一下。

对于java工程师来说,几乎没有多少不了解Spring了,Spring Boot 、Spring Cloud等等也是信手拈来。但是很多和我一样的新人对于Spring的源码还是了解的不深,但是看过几遍之后,觉得还是有意义的。

众所周知,Spring的核心特性就是IOC和AOP

IOC(控制反转)是依赖倒置原则的一种代码设计思路。就是把原先在代码里面需要实现的对象创建、对象之间的依赖,反转给容器来帮忙实现。IOC容器主要通过注解和XML的形式来配置类之间的依赖关系,降低了类之间的耦合关系。IOC

AOP(面向切面编程)则是Spring的另一个核心特征,它把一些与业务无关,却为业务模块所共同调用的逻辑封装起来,比如日志记录,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。它主要由JDK动态代理和CGLIB代理实现。

至于Spring bean的声命周期,我们先看下图,然后再慢慢讲。

因为是面试,我们不用讲的非常细,心中有图然后翻译出来就行了,具体的内容,大家可以自己打开编译工具,然后找到这个类ClassPathXmlApplicationContext,找到这个方法往下看就行

Bean的生命周期:

createBeanInstance() -> 创建实例

populateBean() -> 属性赋值

initializeBean() -> 初始化

1、在doCreateBean方法中调用createBeanInstance进行实例化

2、还是在同一个地方,赋值并初始化我们的bean

但是Bean生命周期内的拓展点非常的多,远远不是上文这一点。 我们可以这样总结一下:

代码语言:javascript
复制
1、实例化Bean对象
2、设置Bean属性
3、如果通过各种Aware接口声明了依赖关系,则会注入Bean对容器基础设施层面的依赖。
Aware接口集体包括BeanNameAware、BeanFactoryAware和ApplicationContextAware
分别注入Bean ID、Bean Factory 和ApplicationContext
4、如果实现了BeanPostProcesser,调用BeanPostProcesser的前置初始化方法postProcessBeforeInitialization
5、如果实现了InitializingBean接口,则会调用afterPropertiesSet方法
6、调用Bean自身定义的init方法
7、调用BeanPostProcesser的后置方法postProcessAfterInitialization
创建完毕
如果我们要销毁的销毁话
8、容器关闭前调用DisposableBean的destroy方法和自身的destroy方法

二、你讲的很精彩,那么能不能顺便讲一讲AOP的实现方式?

AOP的实现主要是通过JDK动态代理和CGLIB代理来实现,这两种方法随着java的发展,在效率上已经没有多少区别,主要的不同点在于一个是JRE提供给我的,一个是需要依赖第三方jar包实现。

不,这不是最重要的区别。

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,被JDK动态代理的类必须实现接口

而CGLIB动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。因为才用的方法是继承,所以该类或者方法最好不要声明成final的。

三、可以讲一讲HashMap的底层原理吗?

这道题真的可以说是必考。。。或许每个面试官都回答过这个问题?

首先,我们知道HashMap是一个集合,键值对的集合,源码中每个节点用Node表示。

其次,底层通过数组+链表/红黑树来实现。

HashMap的初始容量是16,负载因子是0 75,扩容方式为newsize = oldsize*2,size大小为2的n次幂 扩容后一定会变成2的n次幂 每次扩容时,原数组中元素依次重新计算存放位置,并重新插入。

HashMap在JDK1.7版本的头插法实现元素插入,到了JDK1.8版本升级成尾插法,为什么这样?因为采用头插法可能出现死链。同时,1.8还是先插入后扩容。

讲到了红黑树,我们再来讲讲为什么用红黑树?

红黑树性质 性质1:每个节点要么是黑色,要么是红色。 性质2:根节点是黑色。 性质3:每个叶子节点(NIL)是黑色。 性质4:每个红色结点的两个子结点一定都是黑色。 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。

因为比平衡树快:

代码语言:javascript
复制
(1)AVL树是更加严格的平衡,因此可以提供更快的查找速度,一般读取查找密集型任务,适用AVL树。
(2)红黑树更适合于插入修改密集型任务。
(3)通常,AVL树的旋转比红黑树的旋转更加难以平衡和调试。

四、不错,不知道你有没有听过G1垃圾回收器?

G1采用了分区(Region)的思路,将整个堆空间分成若干个大小相等的内存区域,每个分区也不会确定地为某个代服务,可以按需在年轻代和老年代之间切换。

G1和CMS一样,采用的是分代回收机制。

**Young GC ** 当Eden区的空间占满之后,会触发Young GC,G1将Eden和Survivor中存活的对象拷贝到Survivor,或者直接晋升到Old Region中。Young GC的执行是多线程并发的,期间会停顿所有的用户线程(stop-the-world)。

Old GC / 并发标记周期

  • 1、初始标记:这个阶段会stop-the-world,它伴随着一次Young GC,然后对Survivor区的对象进行标记
  • 2、扫描根引用区:从上一阶段标记的根区域中,标记所有拥有老年代对象引用的存活对象,这是一个并发的过程,而且必须在进行下一次Young GC之前完成
  • 3、并发标记:寻找整个堆的存活对象。这个阶段是并发执行的,中间可以发生多次 Young GC,Young GC 会中断标记过程
  • 4、重新标记:这个阶段会stop-the-world,同时完成最后的存活对象标记。它使用了比 CMS 收集器更加高效的 snapshot-at-the-beginning (SATB) 算法。这个阶段会回收完全空闲的区块
  • 5、复制/清除:G1统计存活对象和完全空闲的区域,完全空闲区域将被重置回收。

五、你对消息中间件了解多少

在工作中,比较常见的是rabbitmq、kafka、Rocketmq这几种消息中间件,我所在的公司现在用的是rabbitmq。 面试官问我们这个问题,其实是希望我们讲讲工作中的业务场景,这个业务场景中为什么要使用消息中间件。

消息中间件看起来很复杂,其实核心说起来就是:解耦、异步、削峰。

解耦:RPC的调用是强依赖的,系统之间的调用会存在耦合,解耦就是把本来耦合在一起的几个系统给分开,通过消息中间件可以将业务上弱依赖、系统调用上的强依赖关系进行解耦。

异步:其实还是上一步解耦的延生,原先业务上是同步代码采用中间件进行异步操作以后,系统的响应耗时大大降低。

削峰:MQ会提供两种模式消息获取方式:PUSH推模式,PULL拉模式,消息中间件根据自己的处理能力,每隔一定时间,或者每次拉取若干条消息,实施流控,达到保护自身的效果。

但是,引入了消息中间将势必会增加系统的复杂性,需要考虑更多的问题:如何保证消息没有重复消费?如何处理消息丢失的情况?如何保证消息传递的顺序性。

六、哦?那你就讲讲如何保证消息没有重复消费?如何处理消息丢失的情况?如何保证消息传递的顺序性?

诱引面试官问你擅长的问题,但是很多时候面试官都会一笑而过,假设今天没有一笑而过

如何保证消息没有重复消费?

有时候重启系统、重启应用等突发事件发生时可能会无可避免的产生MQ的消息重复推送。

但是重复消费并不可怕,只要我们考虑到消息的幂等性就行了。

如何保证幂等性? 比如我们可以在写数据库的时候,根据主键查询一下,如果有,那么就说明已经消费过了。 或者可以用redis来写操作,redis的set有天然的幂等性。 比较常用的就是生成一个全局唯一的订单ID,到了消费者这里,可以根据这个ID进行判断。

如何处理消息丢失的情况?

消息丢失主要有三种情况,第一是生产者丢失了数据,第二是MQ丢失了数据,第三是消费者弄丢了数据,这次我就以rabbitmq来举例子讲讲如何处理消息丢失的情况。

一般来说。如果我们要确保生产者消息不丢失,可以开启confirm模式,在生产者那里设置开启confirm模式之后,每次写的消息都会分配一个唯一的id,然后如果写入了rabbitmq中,rabbitmq会给我们回传一个ack消息,告诉我们这个消息ok。如果rabbitmq没能处理这个消息,会回调我们一个nack接口,告诉我们这个消息接收失败,我们可以重试。而且我们可以结合这个机制自己在内存里维护每个消息id的状态,如果超过一定时间还没接收到这个消息的回调,那么我们就可以重发。

面对rabbitmq自己弄丢数据这个问题,我们必须开启rabbitmq的持久化,就是消息写入之后会持久化到磁盘,哪怕是rabbitmq自己挂了,恢复之后会自动读取之前存储的数据,一般数据不会丢。除非极其罕见的是,rabbitmq还没持久化,自己就挂了,可能导致少量数据会丢失,但是这个概率较小。

如果消费者丢失了消息,这个时候可以用rabbitmq提供的ack机制,简单来说,就是我们关闭rabbitmq自动ack,可以通过一个api来调用就行,然后每次我们自己代码里面确保处理完的时候,再程序里ack一次。这样的话,如果我们还没处理完就没有ack了。这个时候rabbitmq就会认为我们还没处理完,这个时候rabbitmq就会把这个消息分配给别的消费者去处理,消息是不会丢失的。

如何保证消息传递的顺序性

如果我们有一个queue,多 consumer。生产者向 RabbitMQ 里发送了三条数据,顺序依次是 ABC,压入的是 RabbitMQ 的一个内存队列。有三个消费者分别从 MQ中消费这三条数据中的一条,结果消费者2先执行完操作,把B存入数据库,这样就造成了消费顺序混乱。

我们可以拆分多个 queue,每个queue对应一个 consumer。或者可以一个queue只对应一个 consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理。

时间也不早了,今天的面试就到这里吧。

关于面试题这个专题,我会慢慢夹杂在java专题内更新,一次不会更新很多题,但是都是一些我或者其他小伙伴遇到的实际真题,面试题的内容也不会写的很底层,很专业,只是尽量在短时间内说清楚问题就好了。如果大家有什么遇的高频题目,也可以给我留言,我会一起写到这个专题里面。

我的微信:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、面试者你好,我们开门见山,能跟我介绍一下spring的核心特征吗?包括Spring bean的生命周期也可以讲一下。
  • 二、你讲的很精彩,那么能不能顺便讲一讲AOP的实现方式?
  • 三、可以讲一讲HashMap的底层原理吗?
  • 四、不错,不知道你有没有听过G1垃圾回收器?
  • 五、你对消息中间件了解多少
  • 六、哦?那你就讲讲如何保证消息没有重复消费?如何处理消息丢失的情况?如何保证消息传递的顺序性?
    • 如何保证消息没有重复消费?
    • 如何处理消息丢失的情况?
    • 如何保证消息传递的顺序性
    • 时间也不早了,今天的面试就到这里吧。
    相关产品与服务
    消息队列 TDMQ
    消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档