资深技术面试官教你这样准备 Java 面试

那年仲夏 提交于 2020-02-14 14:14:53

  Java能力和面试能力,这是两个方面的技能,可以这样说,如果不准备,一些大神或许也能通过面试,但能力和工资有可能被低估。再仔细分析下原因,面试中问的问题,虽然在职位介绍里已经给出了范围,但针对每个点,面试官的问题是随机想的,甚至同一个面试官在两场相似的面试里,提的问题也未必一样。

  也就是说,如果让面试官自由提问,那么一旦问到你不熟悉的点,你可能就答不上,如果运气不好,再外加上不知道面试引导技巧等因素,真有可能面试官的提问全落在你不熟悉的范围内,这样就非常可惜了。与其这样,还不如事先准备外带面试引导,这样或许你的能力未必行,但你可以尽可能地通过引导展示你的亮点,从而提升面试通过的可能性。在本文里,就将讲述事先准备Java亮点和面试中引导面试官提问的技巧。

  根据职位介绍微调简历,这关系到能否有面试机会

  虽然这点和本文的主题无关,但如果没有面试机会,那甚至无法展示引导技能,所以还是来啰嗦一下。筛选简历的人,除了会看学历专业等硬条件外,更会看相关经验的商业项目经验,这在职位介绍上一定能体现出来,比如初级开发,一般需要SSM等框架的1年经验,高级开发一般需要3年,再外带些诸如Netty,数据库调优等方面的技能。

  如果看到一份简历上,没有明显的相关商业项目经验(学习项目不算),那么这份简历甚至没面试机会,这就是为什么很多初级开发简历大多石沉大海的原因。其实职位介绍上提到的技能,甚至很多初级开发应该也有项目经验,但这些人就不写清楚,这可能只能怪自己了。这块给出的经验如下。

  1、简历上多积累商业项目经验,而且里面用到的技术尽可能是Java的,如果你可以凑出半年商业项目经验,那绝别写5个月。如果是毕业生缺乏商业项目经验,也得多找些学习项目写到简历上,至于帮老师干的项目以及实习项目,那当商业项目写。

  2、一般职位介绍里,大多提到SSM,Oracle等技术,这些技术在你的项目里,至少应该用过其它类似吧,那么别客气,这些技术关键字尽可能地出现在你简历中的项目介绍里,比如人家要有Oracle经验,你哪怕是有MySQL,也写上,不写就说明你没数据库开发经验,写了就算有相关经验,类似技术点也照此办理。

  3、每份工作的技术要求一定不同,那么你在投简历前,一定得微调,在你项目里做过的前提下,尽可能在你这份简历中,体现出相关技术。

  4、一般对出初级开发,如果没至少半年Java(可能再具体下是SSM等框架)商业项目经验,而且简历里看不到职位介绍里出现的数据库,框架等技能关键字,这份简历基本没机会,高级开发一般是要3年相关经验。

  5、这里不提倡编项目,也不提倡编技术,即你项目里没用到的技术你写到简历中,但话说回来,一般公司要求的技术都很普通,你在项目里哪怕没做过,好歹同事有人做过,你可以看下相关代码,或者你参与过调试此类问题。

  所以哪怕是初级开发,你的技能应该能对上大多数职位介绍,如果对不上就学,也应该很快能对上,只要你的简历上有足够的Java商业项目经验,而且出现大多数技术关键字,至少能有面试机会。

  结合项目和线上问题,优先准备分布式组件的亮点

  面试一般从介绍项目开始,在我的如何在面试中介绍自己的项目经验这篇博文里,给出了相关内容,但本文的主题是事先准备外带面试时引导,那么在面试前,该如何准备亮点呢?先从最值钱的分布式组件亮点准备起。

  比如可以准备通过看日志,解决过Redis、Dubbo等方面的线上问题。这块其实连初级开发也有机会接触,比如Dubbo方面,超时时间没设好,比如设了10秒,平时没事,但一旦订单模块调风控模块出错,过了10秒再返回出错,这样导致整条(基于Http的)链路长时间保持,累计起来就导致资源耗尽最终系统崩溃,或者Redis超时时间没设或设置很长(1个星期),导致Redis的内容在内存中缓存过多,导致OOM问题。这些问题,哪怕是初级开发,应该也有机会接触。

  这方面该怎么准备?

  1、简历上写上在项目里用过Redis或Dubbo组件,并排查过类似问题。

  2、看些基本的Redis和Dubbo接口方法。

  3、尤其看些可能导致问题点的配置,比如超时时间怎么设。

  4、复习下Linux命令,了解如何通过Linux命令看日志排查问题。

  上述是最基本的,如果有MyCAT、Netty、Kafka方面的经验,比如Mycat分库字段怎么设,解决过Netty半包和粘包问题,Kakfa解决过因消息重发而导致的不幂等问题,你都可以写到简历上作为亮点。但本文给出的保本技能亮点,比如Redis和Dubbo超时而导致的问题排查,应该大家都有机会接触。

  别光背题,结合你解决过的线上问题或项目讲

  网上有不少分布式(以及其它方面)的面试题,比如Netty或Dubbo底层细节问题,这些有用,但如果你背熟了,面试里最多得到的评价是“了解分布式组件理论”,聊胜于无,如果对于要有分布式组件经验的工作,你就悬了。对于分布式组件,大家实现该如何准备呢?(其实后文提到的亮点也一样)

  1、一定要应用在项目里,因为面试官只关心对应的商业项目经验,比如你的Dubbo是用在订单系统调会员系统方法里,你的MyCat、Netty等是用在什么场景,这点简历上未必能体现出,但面试时一定要说,这样能证明你用过。

  2、分析问题的能力优于开发能力,所以你最好再结合一个场景说明,比如在项目介绍时,你外带一句,Dubbo方面我解决过因超时而导致的问题,然后等面试官来问,问的时候,你大致说下,然后面试官看你对Linux看日志的命令,以及Dubbo关于超时时间的配置以及问题上下文说得没毛病,那么应该也就信了。

  3、这时可以再结合一些面试题准备下细节,比如看Netty堆外内存,线程模型,Redis数据结构。有些面试官听你说出解决问题的说辞,可能就不问了,有些可能会再问些底层问题,那么你这时候再说下。

  4、这里大家可以对比下两种表现方式,一种是什么也不准备,或者只准备背网上的题目。等面试官问,那么面试官一定不客气,想到哪问哪,比如Netty会问很细,你平时的项目经验未必涵盖到,如果你再无法结合应用讲清楚,那面试官可能认为你只有理论经验。

  另一种是项目介绍时抛出,而且找机会通过解决过的实际问题抛出,外带稍微了解下细节,这样不仅能很容易让面试官感觉你有实际项目经验,更能展示“看日志解决实际问题”的能力。两者差别一看就知道,更何况其实只要方法得到,准备其实也不难。

  数据库调优、虚拟机调优及排查OOM问题的说辞

  按值钱的技能排序,对于一般的初级和高级开发而言,除了分布式组件,下面就是调优方面的能力了,具体可以是分布式调优,这之前讲过, 还有数据库调优和虚拟机调优。同样除了在简历上明写之外,还该做哪些准备呢?

  数据库调优:

  1、熟悉索引,包括索引结构,复合索引和回表,这块应该大家都会说,同样要结合项目案例说。

  2、单机版,通过看执行计划,调优SQL语句,这块怎么准备?项目中,会在Linux上设置,如果有超过10秒的SQL就打印出来,然后通过执行计划看耗时点,比如大多是走全表扫描,或者有了索引没用到,或者子SQL运行了多次,再往深讲就是Oracle里连接方式不对。你通过执行计划看到问题所在后,就对应修改,比如建复合索引,或者通过with语句把子查询提取出来。

  总之这里你得体现出通过日志看长SQL,以及通过执行计划看耗时点。至于如何修改,大多数候选人都能说,但你更知道前两点, 就比别人强了。

  3、如果你感觉还有能力,可以再讲些MyCAT分库分表和Redis方面的调优能力,毕竟这块涉及到分布式组件。这方面可以准备的项目说辞是:比如业务请求里,会经常用公司ID向风控模块看风险情况,那么就可以用ID做键,风控字段做值,另外再把null放到键里,以放缓存击穿。

  另外对于一个千万级别的大表,你可以用ID作为分表字段,分10个表,根据最后一位的值定位到具体的表。同时排查所有的SQL语句,把一些可能全表关联的SQL语句,比如带group by和多表关联,或者用Java业务写,或者优化。同时再网上看些面试题准备些相关MyCAT和Redis的语法说辞。这样你会额外增加“分布式性能调优”方面的经验。

  在虚拟机方面,我另外有篇博文《在面试中如何展示虚拟机和内存调优技能》,大家可以照着准备,总之也是先结合项目展开,然后围绕虚拟机结构展开调优技能,再可以照这篇文章内部类、final与垃圾回收,面试时你一说,面试官就知道,进一步展示你的能力,同时再能照如下的范例,说出你解决过的OOM问题:

  第一步,发现系统很卡,或者日志里频繁出现OOM异常。

  第二步,用dump文件看OOM时的内存镜像,看的工具可以是JMAT。这两个步骤是通用的。

  第三步,通过dump文件,再结合日志上下文,发现了OOM的原因,比较简单的原因是Redis缓存超时时间过长,或者是ThreadLocal里的对象用好没remove(这块还涉及到弱引用,大家可以自己去查,本文不展开),或者创建线程池时,等待队列设置成了无界。

  或者你在Mybatis里,where条件都是带if的,即如果传入id和name再拼装where id = xxx之类的语句,在一种场景里,都没传条件,所以where后面不带条件,把数据库里记录全捞出来了,导致OOM。

  如果你甚至可以说到Netty堆外内存管理不善而导致的问题,如果能说到这个程度,甚至面试架构师都行。

  第四步,解决。发现问题后,对症下药解决就很容易,比如降低Redis超时时间,或者修改好对应的代码。但既然你说是根据线上问题排查出来的,那么就得说如何解决,善始善终。

  总之这里是结合线上问题发现的,所以就别说些因Connection对象没关闭,大的HashMap用好没clear之类的问题了,倒不是这些原因不会引发OOM问题,而是这些问题大多会在上线前测试阶段解决掉了,你再把它们说成线上问题,可能会暴露你们项目组能力不行。

  Java核心方面:准备集合,线程和异常处理等方面的亮点

  通过上述分布式组件和调优方面的说辞,你展示的能力已经比别人强很多了,虽然相比之下,Java核心方面的能力属于单机版的技能,但毕竟属于基础技能,你除了基本问题之外,也得适当准备亮点。如下给出些同样适用于初级开发的亮点。

  1、集合方面,可以准备下HashMap和HashCode的底层代码,同样可以准备下ArrayList和快速失效(fast fail)的底层代码,然后再进一步看下ConcurrentHashMap的读写并发管理部分的代码,因为其中包含volatile,散列表数据结构和线程并发部分的技能。

  而且JDK1.7和1.8 ConcurrentHashMap的底层代码实现起来还不同,你如果找到机会通过这个对象展示多线程并发和数据结构的能力,或许Java核心方面,面试官就不问别的问题了。

  2、线程方面,准备下锁、volatile、线程池和ThreadLocal的说辞,具体通过ConcurrentHashMap了解下锁(1.7)版本和synchronized+volatile(1.8版本)的用法,以及ThreadLocal里可能引发内存泄漏的问题,这些点网上都有,本文就不展开了,其实也未必多,能讲清楚就行了。

  3、异常方面,准备下你在项目里的异常处理方法实践说辞,比如尽量缩小try...catch的范围,finally从句里放释放资源的代码,catch里应尽量处理异常,先用IOException等专业异常处理,再用Exception兜底,以及尽量缩小异常的影响范围,别让程序一遇异常就崩。

  Java核心方面,其实还有很多可以挖掘的点,比如String、final关键字等,而且Java核心方面,网上面试题太多了,这里就不再展开了。

  同样这里要结合项目案例,比如在测试阶段发现了因为遍历集合而导致的问题,同时展开快速失效,或者在压测阶段发现因HashMap在高并发场景下丢数据所以用ConcurrentHashMap,同时展示其中的volatile和并发等细节。

  其实上述技能不复杂,初级开发照样能说,但涉及到了底层代码,尤其ThreadLocal还涉及到弱引用和OOM问题,更能体现实力,哪怕你经验未必比人家多,但你面试时能结合底层代码展示,想都不用想,面试官一定看好你。

  介绍项目时,抛出准备过的亮点,别展开

  上文里给出的是面试准备的技巧,按值钱角度分析,讲了分布式组件、数据库和JVM调优以及Java核心方面的技能,更重要的是,你是结合实际项目准备的。

  台上一分钟台下一年功,如果准备得当,面试时你就可以发挥了。先是在自我介绍环节,你除了介绍基本情况学校学历外,还可以综合说明,比如用过Redis组件,有过数据库和JVM调优经验,有过压测经验(下文会讲),有过排查OOM方面问题的经验等,总之别客气,准备了就说。

  然后进入到项目介绍环节,除了介绍项目背景,开发情况以外,你再结合业务说,这里给出若干说辞范例。

  1、这个项目里,我们用到了Dubbo作为模块间的调用,我除了写代码外,还解决过因Dubbo超时也引发的问题(别展开)

  2、在数据库方面,我除了实现技能外,还做了数据库调优、具体用过索引、执行计划、Redis缓存和MyCAT分库分表,最后两点自己斟酌。

  3、在项目里,每个请求我们会用一个线程处理,其中用到了ThreadLocal对象(结合业务引出ThreadLocal),对此我还解决过因ThreadLocal和线程池设置不当而引发的OOM问题。同时这里可以抛出准备过的其它OOM问题说辞。

  4、在这个项目里,我参与过压测,并在压测过程中解决过 OOM问题,并通过看日志优化代码,从而改善了系统的响应时间。

  5、在这个项目里,我会结合Cat系统监控长SQL问题,一旦出现,我会通过看Linux日志排查问题。(展示看日志排查问题的能力,同时可以进一步展示你准备过的技能)。

  大家可以看到,上述结合项目抛出的亮点时没有展开,因为这时属于项目介绍阶段,如果展开的话可能会让面试官感觉你条理不清晰,而且抛出的亮点都是属于分布式和调优等高级技能。对一些Java核心方面的单机版技能,别人或许当成宝,你可能都掌握的值钱技能太多,都不算什么了。当然,后面有机会,你还是要展示Java核心部分的亮点,只是优先讲更值钱的。

  回答技术问题后,可以引导到你准备过的亮点上

  你介绍项目时,由于已经抛出了足够多的亮点,面试官自然而然就会往这方面提问,这样就达到了引导效果。比如听你讲到Redis缓存,自然就会问了, 问题无非是怎么用?这你可以结合你的项目实际说,底层细节,这块网上资料太多。也就是说,通过项目介绍,你可以把面试官引导你准备好的话题上,这还不算,在回答问题的时候,你照样还能引导,如下给出些引导的技巧。

  1、比如你在回答Redis相关问题时,如果之前你没机会讲“排查因超时时间过长而引发的OOM问题”,那么还可以展开说,对Redis,我还解决过xx问题,面试官自然会问了,然后再展开。

  2、当你回答好Redis问题后,可以再“顺口”说句,在我们项目里,除了Redis外,还用过Dubbo组件,结果过因Dubbo超时时间过长而导致的问题。然后面试官自然就会问到这块了,你同样可以准备些Dubbo底层细节的问题,这方面也很多资料。

  3、在回答好任何数据库相关的问题,比如索引、JDBC等,你顺口说句,我在项目里,还通过执行计划(或Mycat)优化过SQL技能,然后然开。

  4、在回答好任何集合(如ArrayList)方面问题时,你可以说,在遍历集合的时候,我们项目里会非常小心快速失效问题,然后展开。

  5、在回答好任何线程内存模型,或被问到volatile相关问题时,你就说,我知道ConcurrentHashMap里用到volatile,我能具体说下吗?再结合这个对象,扩展到 线程并发话题,而且这还是结合底层代码讲的。

  6、被问到任何异常处理问题,比如运行期异常,如何自定义异常,那么再引导到异常处理最佳实践。

  7、从ThreadLocal,引出底层的Weak引用话题,再引出JVM结构以及OOM调优方面的话题。

  写到这里我都懒得再写了,在上文里,我已经列出了很多亮点,它们两两横向关联,你说好一个再关联另外一个,足以能全方面展示技能。

  但在扩展时你需要注意,万一面试官没接嘴问,你就要立即停止,或者另外找机会再引导,这时如果再说下去,就属于自说自话了。而且尽量不露痕迹地引导,比如上文给出的范例中,引导的话术大多是,除了xx技术,我们项目里还用到了xx(关联性很强)技术,然后坐等面试官来问。北京代孕威信15023219993 广州代孕威信15023219993 深圳代孕威信15023219993 昆明代孕威信15023219993 上海代孕威信15023219993 天津代孕威信15023219993 成都代孕威信15023219993 北京代孕威信15023219993 重庆代孕威信15023219993 重庆代孕威信15023219993

  也就是说,遇到一些不大自主思考的面试官,你甚至可以通过事先准备外带面试引导,控制面试全程节奏,哪怕是遇到一些大厂的面试官,你同样可以据此把问题引导你熟悉的范围,最多就再根据网上面试题再准备些(Dubbo、线程模型等的)细节问题,毕竟人的思维方式的很相似的,听到你“随口”这样一说,很有可能就“接茬”向下提问了。

  引导到压测和排查线上问题经验等值钱话题

  比起分布式实践技能,更值钱的是压测和排查线上问题和项目上线方面的经验,这在面试时非常容易引导,也就是一两句话的事,比如你随口一说:“在这个项目里我做过压测,而且有过根据压测结果调优系统的经验 ”,或者说,在Dubbo等方面,我排查过线上问题。自然前提是你要做过,等到面试官提问时,压测方面你可以给出如下的说辞。

  1、你参与全链路压测,即相应的同学坐一起,用Jmeter发请求,用zabbix监控CPU内存指标,同时看日志监控问题。

  2、压测是用测试环境,当然你也可以说是线上环境,如果是线上环境的话,更要监控,一旦出现CPU等负载过高,立即终止。

  3、比如用Jmeter发500个线程,每个线程起5个交易,这些交易用2秒做完,那么每秒的压力是1250。

  4、最关键的是,你要根据压测结果改善性能,比如通过压测,发现了线程池设置参数时,把等待队列设成了无界,或者有模块IO对象没关,或者ArrayList没clear,从而导致了OOM,或者发现高并发场景数据库方面出现了长SQL,然后用执行计划分析,再解决,或者发现了系统日志本来是同步输出的,从而导致性能瓶颈,最后改成异步日志。或者发现数据库是瓶颈,所以再引入MyCAT和Redis。

  总之,压测说辞方面,面试官更关注你分析问题和解决问题的经验,至于发现和解决的问题,只要能说得过去就行了,况且你还能借此展示分布式和调优方面的技能。而排查线上问题方面的经验,你可以用如下的步骤给出说辞。

  1、如何发现?无非是通过CAT监控发现长SQL,或者通过Kibana等工具发现。或者可以说是先期业务埋点,发现交易异常时抛提示。

  2、发现问题后你的态度,通过手机发现问题后,你第一时间看,哪怕不在你的范围内,你第一时间上报。

  3、如何排查问题:通过Linux命令看日志,或者通过dump看OOM的镜像。

  4、分析原因,借此你可以展示上文给出的亮点技能,以及对应解决。

  话说回来,哪怕是初级开发,也有资格参与压测,平时也一定会遇到线上问题,你如果面试时不说,面试官自然不知道,但这块你绝对是大有可为的。

  先找实践机会再提升技能,程序员该挑战更高级的职位

  总结下,本文的主题包括两个,第一结合自身实际,面试前挖掘亮点,第二面试时通过引导,尽量把问题引向自己熟悉的范围。实践起来,技术要结合项目,而且最好再结合你排查和解决过的线上问题,同时回答好一个问题后,再把问题引向同类以及调优方面的话题。

  比如Redis,当你结合项目,压测和线上问题,讲述基本用法和解决过的问题后,面试官可能再会问数据结构,高可用集群和事务方面的问题,这些问题就可以事先准备了。

  对于初级开发,你说好第一部分的说辞,哪怕细节问题没回答上,面试官虽然无法给出“深入了解Redis细节”的评价,但至少能给出“在项目里用过Redis和排查过Redis相关问题”的评价,如果你再结合项目,如本文所示,全面展示调优,Java核心等方面的技能,那么你面试资深高级开发也够了,面试初级开发真就绰绰有余了,如果经验再丰富些,再去面试小公司的职位,更有些委屈了。

  当你按本文所述,准备好相应技能,然后再通过一些面试实践变成面霸后,很有可能你面临的不是要面试什么公司的问题,而是“面试通过后能不能适应更高级职位”的问题。

  不过总是先有实践机会再提升,比如当你是初级开发时,从事第一份高级开发工作时一定很吃力,甚至还会看人脸色,但如果你不追求更高级的岗位,一直陷入低级职位的舒适区不可自拔时,你的竞争力也会逐月下降。

  所以到了必要的时候,你总得根据本文给出到的建议,不断挑战更高级的职位。况且,本文在开篇时就提到,技术能力和面试能力是两个方面,而本文给出面试技巧,都是靠平时技能积累,本文给出的面试建议,能帮助大家更好地在面试中展示亮点。

  希望本文不仅能帮到大家更好地挖掘自己项目经验,更能帮到大家高效地找到自己心仪的工作,最后感谢大家看完长文,本文写了有5个小时,如果大家感觉可以,请多多点赞,有问题也可以多写评论。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!