面试杂思

面试杂思

最近面试了那么几家公司,对于大多数面试官的表现,我都是不怎么满意的。只有蚂蚁金服的面试官我很满意,头条、京东、新浪金融的面试官,我统统给差评。这个问题其实由来已久,奇怪的是,企业似乎没有多大动力去解决这个问题。面试的目的是为了发现合格的候选人,与其要求每个候选人都按照面试官想要的方式去回答问题,不如培训面试官,是他们成为善于发现人才的人成本更低。

我自认为是个还不错的面试官,我一直负责最后一面,一般跟候选人沟通都很顺畅。我自吹一下,经常有候选人面完之后对我们HR说,最后这个面试官人特别好,问的问题也特别有趣。这篇文章我们会系统的讲一下,如何做一个好的面试官,面试官在面试中常犯的错误有哪些。


面试的大流程,基本分为两块。第一块是聊天问问题,第二块是写代码,写代码又可以分为做算法或者做系统设计。这个各大公司都差不多,没有必要赘述。本文重点说的是第一块,聊天问问题这一步。


先说面试的内容。我们画一个非常简单的Vnn图。A代表面试官会的内容,B代表候选人会的内容,C代表A与B的交集。D=A-B,也就是面试官会而候选人不会的内容,E=B-A,也就是候选人会而面试官不会的内容。

大部分普通的面试官会面哪些内容呢?很简单,他们在A中随意的挑选问题,看候选人会不会。是不是,大家想想面试官是不是这么做的。因为E中的问题他显然没有办法问,所以也就只能在A里面随机问了。

那么面试的目的是这样吗?不是。我们应该问哪个区域的内容呢?我们说三个层次。第一个层次,最稳妥的办法,我们面C中的内容。也就是说,如果我们问到一个问题,候选人明显不会,那我们直接跳过这个问题,并且不把这个问题计入面试表现。然而大多数面试官并不是这么做的,他们会暗搓搓的把你这点不会记下来,提交到报告中。

为什么我们不愿意面D区域的内容呢?因为想难住候选人实在太容易了,每个人的发展方向不同,专攻不同,会的东西自然不会完全相同。不信?我问几个java的问题,看看你会几个。java编译器会对synchronized做锁粗化,你知道怎么做的吗?java中ClassLoader加载类的过程是哪几步,分别做了什么呢?加减乘除、位运算、布尔运算符的优先级列举一下?java的对象一定是分配到堆里吗,什么情况下分配到栈上?G1收集器怎么避免全堆扫描,remember set有没有引入别的问题?我觉得你很可能不会几个,因为这不是什么常见题,有几个甚至可以说有点偏。而据我所知,有一些面试官就喜欢问这种问题,享受那种候选人不会的感觉。这与面试的目的完全背道而驰。

所以,正确的姿势是这样的,准备几个系列的由浅入深的题目,如果候选人根本不会,就换一套。只要候选人有一套答的很完美,这个环节就给满分。考察的点,是C这个区域中,候选人对这些技术到底是浮于表面,还是研究的足够深入。这里列举几个我经常问的系列的问题,作为参考,每个系列内部从上往下由浅入深:

1、MySQL四个隔离级别有了解吗?
Read Committed级别会有什么问题?
这几个隔离级别是怎么实现的了解吗?(三级封锁协议,MVCC)
我举两个transaction的并行执行顺序,你看看你能不能说一下MVCC是怎么保证它的隔离级别的。
MVCC,两阶段锁协议(不要看成两阶段提交协议),能挑一个讲一下吗?

2、jvm垃圾收集有哪些呢?
简单说一下CMS的运作过程?safepoint有哪些?
CMS的重新标记和G1的最终标记,哪些地方相似,哪些地方不同?
G1如何避免全堆扫描?
你觉得这个过程有没有什么问题?

3、JuC这个包了解吗?线程安全的容器有哪些?
HashMap并发会产生怎样的问题?
HashMap死循环问题知道吗,为什么会发生?
java1.8怎么解决的这个问题了解吗?
StringBuffer和StringBuilder在单线程中使用会有区别吗?(答案是没有区别,因为有锁消除)

4、JuC这个包了解吗?线程安全的容器有哪些?
ConcurrentHashMap如何做到线程安全?
ReentrantLock和synchorized主要有哪些区别?
AQS的源码看过吗?实现思路有没有了解?/ synchronized的实现有了解吗?
除了ReentrantLock还有哪些类继承了AQS,是怎么用的呢?/ synchronized的锁升级、降级过程讲一下?

5、我看项目中用了Kafka,topic,partition,consumerGroup的概念?
kafka如何保证发送时的一致性?消费时的一致性?
kafka集群如何运作?一个topic的controller挂了会发生什么?
paxos和zab协议有了解吗,简单讲一下?
kafka使用磁盘做到了接近内存的速度,能讲一下怎么做的吗?

6、cache与db一致性怎么保证?
cache-aside方案的问题一般怎么解决?分布式锁的方案有什么问题?
两阶段提交协议能解决这个问题吗?
两阶段提交协议的问题在哪?
这些方案中,生产你们用哪个,或者你觉得哪个更合适,为什么?

7、redis用的多吗?常用的五种数据结构?
redis大概的性能是什么样子?讲一下持久化?单进程单线程?
redis源码看过吗?五种数据结构的底层实现有哪些?简单讲一下SDS?
redis的rehash的过程了解吗?
redis为什么性能这么高?

8、单例模式?常用的四种写法?
一般用哪种?为什么双重锁几乎从来不用?
spring里面用的是哪种?(其实是可配的)有什么类不能用单例模式,不适合用单例模式的?
装饰模式和代理模式的区别?
说说你对其他模式的理解。

9、分布式锁了解吗?有哪几种方式实现?
redis和zookeeper的分布式锁实现选一个讲讲?
比较一下他们区别?
redis的分布式锁如何解决锁重入?锁的时间太短会怎样?太长会怎样?如何解决?

一口气不打草稿竟然写了这么多。每个系列从第三个问题开始就不那么好回答,基本要看候选人回答的情况来决定后面该怎么问。上面我们说了面试时最稳妥的内容选择,就是面C中的内容,如果面试者压根不会,就跳过,并且不计分。所有问题中,只要有一个问题了解的比较深,就给过。而不是一个问题不了解,就不给过。

如果你已经掌握了这种面试方法,下面将进入第二个层次。把C扩展到A,问A中的内容。假如候选人不会,那么给他讲解明白,看他对这项技术有什么理解?然后可以问的问题就是,为什么这么实现呀,其他地方有没有跟这个实现相同的思想啊?这些问题就都是开放问题了,要求面试官能够hold住场面。我是不建议在面试中问过多的开放性问题的,尤其是火候不够的时候。

第三个层次,把问的问题再扩展一下,扩展到A+B。这个面试方法,就更加一言难尽了。简而言之,如果他对某项技术自认为了解很深,而你又不懂,你可以让他讲给你听。一来你可以提高自己,而来你可以通过他的讲述过程看他对这个技术是不是真的理解,能不能回答你对这项技术的各种疑问。这个要求就比上一层更加高了,如果你技术不够,很可能听的一脸茫然,最后也不知道该给人家几分了。

总结一下面试内容这个环节,说白了就是一定要问对方会的!不要因为一些问题对方不会就给人家扣分,除非这个是原则上要求必须会的,比如你问对面for循环怎么写,对面不会,这肯定就不给过了。


再说面试的方法。这点也很简单,面试不是考试,和对面坐在平等的态度上,沟通交流即可。面试不是你在挑候选人!同时也是候选人在挑公司!切记!还有一点很重要的是,如果你认为对面答错了,问一下对面为什么这么答,说不定是你理解错了而对面的理解是对的呢?比如你问对方,StringBuffer和StringBuilder在单线程中效率一样吗?对方回答一样,因为有锁消除。如果你没听说过锁消除,你又认为StringBuffer有同步代码块,你会认为对面答错了,然后记下,候选人没有深入理解StringBuffer和StringBuilder的区别。恭喜你,你又把一个优秀的候选人推到了其他公司。


一个最常见类型的面试官是什么样子的呢?我们可以总结出来了,问A中的问题,问的非常浅而不是深入,每当候选人有问题答的不好,也不给候选人反馈,直接记到小本本上。是不是非常搞笑?我一共就面了四家公司,就碰到两个这样的面试官,碰到这样的面试官,你就非常生气,因为你有力使不出,对面就在问问边边角角的无聊问题,也不深入,最后人家还觉得你水平差,真是有苦说不出。

我以头条的四面举例。注意,我既不是说面试官人品差,也不是说面试官技术差,我是说面试官作为面试官的水平很差!面试官基本上就是一个个小问题问过去,没有任何一个问题有继续深入考察。

你先来个自我介绍吧!—-好,我是xxxx,blabla。
annotation用过吗?——用过,blabla。。。
你们都用了些什么数据库?——mysql,redis,mongo,kafka,如果把kafka也算数据库的话,blabla。
mysql里面触发器知道是什么吗?——我没用过,不过大体知道是干嘛的,blabla。
常用的集合类?——HashSet,HashMap,Hashtable,各种,blabla。。
哪些是线程安全的?——主要就是JUC里面那些吧,blabla。(后来机缘巧合我知道面试官给我记了答错了Hashtable是否线程安全。感情是因为我上个问题说了hashtable,这个问题没说?我一脸黑人问号)
用什么多线程?——主要用ExecutorService吧,blabla
Java闭包知道吗?——java有闭包?没听说过啊。我知道python,ruby之类的一般有这个概念,具体我忘了,但是应该是主要关于变量和作用域的一个概念吧,blabla。——对,差不多吧。(然后小本本上记下,对闭包的概念理解有误。我无语了)
我们做题吧。——你就问这么多,不会觉得太浅吗?反映不出我技术水平,咱深入问点呗。(此时我心里有点崩溃)
那我再问点,(找了一下),自动拆装箱知道吗?——知道,但是你要是问我那种等号左右是否相等的问题,我真不一定能答上来,真要把这个都搞定可能得背过。
那位运算优先级和加号的优先级能说一下吗——这个我不敢保证,可能位运算高吧(此处我确实答错),这个就是能加括号就加括号吧,毕竟我记得几个布尔运算符的优先级都不是完全一样的。(小本本记下,位运算和加减法优先级记错)
你看你让我往深里问,我往深里问你又不会——(我内心想法是,你管这叫深?不过我也没直说)我说你可以问jvm各种源代码啊,AQS啊,Hashmap啊,annotation实现啊,redis源码啊,kafka源码啊,ThreadPool深入理解啊,垃圾回收啊,都行啊。
面试官笑笑,也没问,后来就做题了,我感觉他可能不太会这些。。。好在他最后给我过了,但是我对这个面试体验真的很不满意,我根本没有回答任何可以展示我技术水平的问题,过了又怎样。

可以看出,这个面试官问的问题没有主次,基本就是在A中随便挑问题。其实这个面试流程中,有大量可以深入问的机会,MySQL,redis,kafka,annotation,executorservice,HashMap,都提到了,完全可以进一步问更加深入的问题,实际进展实在令人失望。问完了解不了解就继续下个问题了,没有任何深入沟通。面试方法更是不对,如果你认为对面答错了,跟对面沟通一下,看看对方怎么想的,很多面试官都喜欢根本不沟通,自己往小本本上记,极度差评。

我对蚂蚁的面试官就感觉很不错,以一面为例,问了很多问题,但最主要的时间都在探讨整个redis分布式锁中的各种问题,基本上各种细节问了个遍。当然这些我也都会,面试官也很满意,这就是一个不错的面试流程。

最最搞笑的是新浪金融的CTO,给人印象极差。后来我问了一下帮我推那边的猎头,好多人反应如此,听了以后我心里舒服多了。问问题不给任何反馈,而且觉得自己的比较对。举个例子,问我分布式系统中多种db怎么保证一致性,我说常用做法是两阶段提交协议,他跟我说因为两阶段提交协议有漏洞,所以不能用。。。我就无语了,你当阿里TCC是干嘛的,有漏洞谁还用啊,只是有使用条件而已。如果网络是内网,系统可用性能够到达99.99%,用两阶段提交协议基本是没有问题的,不过既然他坚持这种看法,我就说用消息队列解耦也是一种常用的方法,然后他就换问题了,没有反馈,也不知道对不对,我猜是对了。然后我被这货用“风格和我们公司不一样”这种奇葩理由拒了。PS我跟前两个面试官聊的都很开心,他们表示我技术很强。。。。算了,反正最开始我也没想去,只是想去面面,拿个offer而已。但是,我很气愤。


咳咳,我要稳重,不吐槽了。总结一下,面试不是考试,是一种沟通,目的在于衡量对方的技术水平,技术深度,好学程度,等等等等。要尽量把双方之中可能有疑问的点沟通清楚(比如对方答错了,要问他为什么这么答),要尽量问对方会的问题。不管你给对方过还是不给对方过,你都花了公司的钱,公司为找来的每个候选人都是付出了不小的成本的,错误通过会使得公司多发一些钱,而不通过会使公司之前的努力付诸东流,因此一定要承担好自己的责任。记住,努力评价候选人的水平是你的责任,是你对公司的责任,而候选人能不能好好展示自己,是他的事情。你的目标是,即使候选人不会展示自己,你也要找到他能力发光的地方。好的候选人总会找到好的公司的,是金子一定会发光,不管他会不会展示自己,哪怕根本没有准备面试,如果他能力强,也一定会被好的面试官看中,被别人的公司收走,你说,这是他不会说话的责任,还是你们公司的损失?

发表评论

电子邮件地址不会被公开。 必填项已用*标注