美团 后端 - 一面 攒攒人品 望二面
更新--等了三天,今天(3.25)终于收到二面邀约啦!!牛客攒人品yyds!谢谢牛客!!也谢谢面试官手下留情!!
面了一个半小时,哭了。。
第一部分:算法题
- 第一题:一个简单的二分查找
套模板一会就a了,然后面试官说他们的算法部分一般要求20分钟,我写的太快了,再出一题吧,我:???? - 第二题:中序遍历和后序遍历构造一棵二叉树
一开始把中序遍历和后序遍历的变量名看反了,写完了之后怎么运行都不对,后来才发现写反了,赶紧改了,然后边界条件也卡了一会,但是所幸最后还是ac了。
面试官还跟我聊我的笔试成绩,说我第二批笔试a了4.3,看得出来我平时有在刷题,然后聊了聊房间爆炸那题为什么没a。
第二部分:计算机网络
- 问题:计科的是吧,开了什么课(回答操作系统啥的),计网学过吗(这学期开的,不过自学了),说说七层模型
回答:老八股 - 问题:post和get的区别
回答:1)一个是取一个发,2)数据放在哪里,3)缓存不缓存 - 问题:你说一个是取,一个是发,那你说说可以把他反过来吗
回答:我认为是可以的,比如servlet编程的时候,我们的doGet和doPost方法甚至是经常相互调用的,这个只是代表一个请求类型对应哪个方法处理罢了,至于方法体里面干嘛,我感觉不一定就必须是一个是取一个是发,但是的话,这种协议一般都是规范,我们一般都是根据规范来开发
第三部分:Java相关
- 问题:Java线程池说一下吧
回答:老八股了 - 问题:你说说几个线程池和对应的阻塞队列是怎么样的
回答:老八股了 - 问题:你刚刚说的那个LinkedBlockingQueue对吧,你有了解他的常用方法吗?
回答:(问这个问题瞬间我就知道下一个问题应该是里面的阻塞和非阻塞了)我虽然不太记得清他里面各个api的名称,但是我记得他作为一个队列是有出队入队方法的,然后会有两种,一种是阻塞的,一种是非阻塞的。 - 问题:那你说说阻塞和非阻塞的方法的区别呢
回答:阻塞就是:当队列空了,读线程阻塞,当队列满了,写线程阻塞,非阻塞的话就没类似的操作。 - 问题:那你说说你刚刚提到的FixedThreadPool里面的那个阻塞队列,他用的是阻塞方法还是非阻塞方法呢
回答:(不会)我认为应该是非阻塞的吧,毕竟他是用于实现CPU密集型的任务,我感觉如果让他阻塞了会不会导致性能下降。
面试官解答:这么说吧,Fix不是固定线程数的吗,也就是他是没有非核心线程之分的,那你结合线程池那个流程,当队列满了此时会去判断当前线程是否小于最大线程数对吧,那既然现在我不区分非核心线程了,这一步也就没必要了,那你想想这里队列满了,我直接阻塞不就行了。
(我直接茅塞顿开,不愧是大佬,言简意赅啊!) - 问题:你说他满了写线程会阻塞对吧,那么一旦不满了,他是怎么通知写线程来写的呢,也就是这种睡眠与唤醒机制
回答:我不太清楚他底层是用的哪一个,但是据我了解,Java中的这个机制有:wait/notify,LockSupport的park与unpark,reentrantLock提供的条件变量等都可以实现。 - 问题:你知道线程怎么中断吗(答:interrupt),你知道线程中断是什么原理吗
回答:瞎说了一下,就说是让他停止运行 - 问题:那问你一个问题,现在有一个for循环,里面都是简单的变量自增这种操作,你觉得中断可以发生在这里吗?
回答:我认为可以,因为无论是多简单的代码,例如您说的自增,他在JVM层面一样是好几个指令,既然有好几个,那应该中间就可以被中断吧。。
面试官:这一块下去多去了解了解哈。
第四部分:Redis相关
(炸裂面试环节!)
- 问题:你用了分布式锁,怎么实现的?
回答:Redisson,结合项目用途说了说--超卖问题 - 问题:你知道他的底层实现吗
回答:看门狗机制+redis - 问题:你知道他用的redis什么数据类型吗,key和value分别是什么
回答:我认为是String类型,因为他只是作为一个锁标志,key的话是调用api传进去的,value的话我不知道底层用的什么 - 问题:key你说是自己传进去的,你用的啥
回答:我锁的是商品列表里面的一个个商品,所以锁的key就是:“productLock” + productId - 问题:你锁的是商品列表里的一个个商品吗,那你认为会不会出现死锁问题?比如A被加锁了,然后去获取B,另一个线程先加了B锁然后去获取A
回答:哦!对!确实有可能出现 - 问题:让你解决你会怎么解决
回答:我会在for之前加一个锁,把这一块操作都变成原子性的即可 - 问题:好,那你怎么确定加锁的名称,也就是刚刚说的key
回答:。。。用商品id连起来?然后下一个线程来的时候,先判断一下大家买的有没有出现相同的商品,出现了就要阻塞 - 问题:怎么实现?
回答:emm,获取锁然后判断名称(纯瞎说,说出来我就知道不对,都被加锁了,还获取啥锁啊)
(事后想想,应该这里是,考虑怎么解决死锁,众所周知,解决死锁的主流方法就是规定获取资源的顺序,大家按顺序获取。所以这里应该是先给productid排个序,大家都按商品ID升序顺序去获取,这样必然就能避免死锁,我这个蠢脑子啊!!!)
面试官: 这一块下去多去了解了解哈。
第五部分:SQL题
- 问题:看你项目用了MyBatis和MySQL,你说说你项目有几个表吧,表之间关系说一下
回答:按表设计说了一下 - 问题:看你应该项目里写了不少sql,写个sql题吧
问题描述:一个表,姓名,科目,成绩,求没有一门课及格的学生姓名
(我就知道面试一问SQL一定是groupby,但是想不出来groupby之后干嘛,然后只能赶紧给一个暴力解法)
回答:换个思路,要求没有一门课及格的学生,那么就是求:该学生不在有一门课及格的名单里面,所以:
select name from t where name not in (select name from t where point >= 60);
面试官说可以,但是有没有更简单的,一句select实现(我当然知道要一句实现啊,我不会才这样的呀)
想不出来,面试官提示了:既然是求没有一门课及格的,那换个说法,不就是该学生最大成绩小于60吗
我:!!!!妙啊,然后瞬间写出来了
select name from t group by name having max(point) < 60;
我还以为我完蛋了。。面试官却夸我说:应届生写出来groupby也不错了,我心想不至于吧,我在的群里不都是大佬吗,就硬夸哈哈哈
第六部分:
- 问题:项目的注册登录说一下
回答:老长了,说一半被打断了 - 问题:你刚刚说了你用了拦截器,你说说这个干吗的
回答:我用了SpringMVC那个Interceptor,然后配置他的拦截路径,如果用户请求过来,我会通过JWT验证机制进行判断是否登录,如果没登录就抛出自定义异常,然后全局异常处理器会去处理 - 问题:说说JWT
回答:概念和验证机制说了一下。
第七部分:Redis
是的,你没有看错!!!我这场面试:除了三个题,基本全是Redis!!!
- 问题:多问点redis吧,我看你用了热点缓存,你说说你缓存了啥
回答:我用string类型缓存了页号-JSON商品列表 - 问题:我不是很理解这种缓存啊,你说说,如果我插入一个新商品,万一他也在第一页,你怎么知道怎么去更新
回答:(说实话到现在还是没听懂这题)emm,insert不是插在表尾的吗,怎么会插在第一页。。。我不太理解您的意思 - 问题:不理解没关系,我就是很奇怪这种热点缓存罢了,一般都是缓存那些爆卖商品的,其实商品列表对于它而言没那么热点,至于商品列表怎么缓存,你了解过list数据类型吗
回答:我当时有对他进行一个技术选型,但是我感觉list太麻烦了,图方便就用了string,因为前端也是要这个json格式的,我直接获取到发给他反而方便 - 问题:你知道主从复制吧,你说说主从复制
回答:主负责写,从负责读,主被写了会发起一个增量复制给从,从会去同步,但是我认为这是没有实时一致性的 - 问题:按你这么说,只要是主从架构都有实时一致性问题咯?
回答:emmm,不理解您的意思
面试官很好,看我不会,给我解答了一整套同步与异步机制 来完成主从一致的区别,学到了。
我:但是redis这种高性能,肯定不希望用同步这种拖低响应时间的机制
面试官:对。
最后问了一些学习方法方面的事情。
反问:
- 面试评价:
夸了一下我能做出来两个算法题+sql题,然后最后说我的项目经历还是多去问问,多去深挖,不要停留表面 - 部门:
基础研发,面试官介绍了一下他们部门是负责一些底层的组件的开发(Cool!!),所以他们部门面试会追求深度和基础,然后解释了一下这就是这次面试他一直在问中间件以及一些很深入的问题的原因(我连忙点头,表示深有体会呜呜呜。。)
体会:
- 全程1.30小时,基本全在问redis,就逮着我的分布式锁,不断地挖,不断地问各种可能出现的问题,拼多多二面以及美团一面接连暴打项目经历,都说了我的项目经历不行,确实该好好复盘深挖项目了!!
- 第一次面试做这么多题,虽然不难,但是中间还是紧张了,甚至想过放弃了一道做过n次的构造二叉树题,还好最后ac了。果然还是要好好加强心理素质,然后多刷题!
- Java并发确实值得更深入学习,今天除了redis就问这个了,深入!!
呜呜呜,写完面经已经两小时了。。。还没美团二面约面电话,xdm我是不是挂了。。。。
攒攒人品,望二面吧!!!