美团 日常实习一面凉经

时间线:12.04 官网投递,12.09发了邮件选择约面时间,12.10一面。面试时间70分钟,已挂。

个人总结反思

这次面试碰到的面试官非常非常好,很感谢这位面试官。写算法题过程中会引导思路,考察八股时也会告诉我不会的该怎么答,以及纠正错误。整体面试体验是这几场以来最好的一次,可惜最后挂了

面试过程暴露了很多新的问题,最大的锅是自己算法写凉凉了。当天晚上面完之后估计已经挂了,心情一塌糊涂。又匆匆地开始预习编译原理准备12.11晚上的期末考试,一整个晚上都没怎么睡着。

之前有很长一段时间没写链表类的题了,一直在刷图论和动态规划。结果碰到这么两个链表题,当时心里就一惊。现在面试过程中答八股和项目相关问题时不再那么紧张,但是写算法的时候还是冷汗直冒。

第一个算法写了10分钟没写完,面试官提出换题。结果第二个写了整整二十分钟,最后还是有bug。面试结束之后,我去重新看了一下代码,检查了近十分钟发现是翻转链表的子函数漏了一行很关键的代码。补上这行就跑对了,真是草了。后续刷lc上的算法必须得直接在网页端编写代码和寻找bug,之前一直在vscode上写顺手了,面试过程中那种直接搁平台上写的情况还是有些不适应。

美团的Java技术栈考察重点有相当一部分是JVMJUC相关,问的很多。这部分之前背过一些八股,但JVM自己忘了不少,导致面试的时候很多答不上来。八股这东西真是背了忘忘了背,难搞的很。需要再过个1-2轮,才能到达和面试官吟唱的程度。

面试内容如下

1)面试官介绍部门业务

2)自我介绍

3)课程是都结束了吗?

4)你这几个项目和技术栈都是通过什么渠道去学习的?

这边答了通过各种技术博客、网站,以及B站和YouTube上的网课学习。也会和一起找工作的哥们交流学习进度和经验。

5)向你们大学期间,Java相关的技术栈和MySQL相关的知识,基本都是学过了是吗

答了是这样,基本都是靠自学,学校教的鸟用没有

6)都是通过自学,就是看一些书籍和网课视频去自学的是吧

7)然后你这个项目我看都放github上了,我点开看了一下。

这边我和面试官都绷不住笑了,估计是看到了我github主页里自学技术栈过程中的commit的一些吐槽和学习记录,以及心态转变、日记记录。

项目相关

1)首先这个校园生活服务平台,它提到了缓存的一个处理。我想了解一下哪些数据加了缓存?

答了主要是商铺数据信息,还有博客主页的一些带货链接,放在缓存里方便用户后续查询跳转。

ps:这边其实不太记得啥东西加缓存了,缓存里一般放的是高频热点数据和首页推荐流

2)这里面提到了基于 Cache Aside(旁路缓存)模式,你还了解其他的模式吗?

答了Cache Aside对应的读写策略(自己忘记剩下那两个模式叫什么了),“先删缓存,再更新数据库”可能导致脏数据读入缓存的问题。

ps:剩下那两个分别是Read-Through/Write-Through(读写穿透)和Write-Behind(异步写入/写回)。

3)你的这个缓存有设置过期时间吗?过期的机制是怎么实现的?

答了设置过期时间TTL,并且采用惰性删除的策略。(但这边表述的还是不太流畅)

ps:Redis的底层过期机制:

惰性删除:客户端访问key时,Redis检查是否过期,过期则删除。

定期删除:Redis后台线程每隔一段时间随机抽取部分设置了过期时间的key进行检查和删除。 这样结合既避免了CPU空转,也防止了过期数据长期占用内存。”

4)热点商户信息使用互斥锁机制,这个可以介绍一下吗?是什么场景下使用的?

答了热点商户在实际生产中会有大量用户查询。加锁是为了保证同一时刻只有一个线程去查询数据库,防止缓存击穿。

ps:此处答的不太好,应该提到在热点key缓存过期的瞬间,如果有海量的并发请求打过来,会全部穿透到数据库,造成数据库宕机。

5)扣减库存的问题,这个你是怎么实现的?

答了这个问题和超卖问题,使用乐观锁CAS机制并加上版本号进行校验,去扣减库存。

算法考察

1)lc 25:k个一组反转链表2)lc 445:两数相加 II

JavaSE & JVM

1)Java集合包含哪些类?

答了有list、Set、Map之类的(这边也没答全)

2)Map的话哪些是线程安全的,哪些是线程不安全的?

答了HashMap不安全,ConcurrentHashMap安全。

3)ConcurrentHashMap 是怎么实现线程安全的?

这边答了底层通过CAS机制,在每个搜索位连接链表或红黑树。对头节点加锁。(但其实不太对)

ps:ConcurrentHashMap在 JDK 1.8 之后,采用 CAS + synchronized 来保证并发安全。锁的粒度更细,只锁住当前哈希桶的头结点。如果该桶为空,就采用CAS插入;如果不为空,就使用 synchronized 去锁住头结点进行链表或者红黑树的操作,这大大提高了并发性能。

4)Java里的反射和动态代理一般是在哪些场景会使用呢?

这边答了AOP底层利用动态代理。JDK 动态代理针对实现了接口的类,CGLIB针对没实现接口的类,通过反射创建子类重写方法。

ps:这样答感觉不太恰当,反射的话主要用户框架开发,比如Spring IOC容器实例化Bean;或者说JDBC加载驱动。

5)Java中的异常分类

这个忘了,然后随便扯了IOException和OOM(完全答错了)

ps:查了一下异常Exception应该分为运行时异常RuntimeException和非运行时异常(IOException、ClassNotFound等等)

6)JVM的内存管理(内存分区)可以介绍一下吗?

这边答了分为栈、堆、方法区、元空间、程序计数器。堆是线程共享,栈是线程私有。

ps:有很多地方答错了,没记太清。JVM 运行时数据区主要分为线程私有和线程共享这两个部分。线程私有的包含程序计数器、虚拟机栈、本地方法栈;线程共享的包含堆和方法区(JDK 8中采用元空间实现)

7)CMS垃圾回收器的过程讲一下,分了哪几个阶段?

不会

ps:查了一下,CMS收集器分为初始标记、并发标记、重新标记和并发清除四个阶段。

8)常见的垃圾回收算法你了解哪些呢?

这边吟唱了标记清除、标记整理和复制算法(忘记答分代回收算法了,问题出在我忘记“分代回收”这个名词上面)

9)标记待清除的对象是根据什么策略来标记的?

这边吟唱了引用计数法和可达性分析算法

10)类加载器的分类,有哪几种类加载器?

不会(完全忘了)

ps:应该是启动类加载器、扩展类加载器、系统类加载器/应用程序类加载器、自定义类加载器

11)类加载机制里,双亲委派机制了解吗?

答了创建对象时委托父类去创建,不用重复加载,解决安全问题,比如防止黑客篡改 System 类。(这边答的时候说岔了,把加载类说成创建对象)

ps:更恰当的说法应该是:双亲委派模型指的是一个类加载器收到类加载请求后,它自己不会首先去加载,而是把请求委托给父类加载器。层层向上,直到顶层的启动类加载器。只有当父加载器反馈无法完成加载时,子加载器才会尝试开始自己加载。其好处是安全性(防止核心API被篡改)和避免重复加载(父类加载过的类,子类无需再加载)。

12)外部引入的jar包是通过哪个类加载器加载的?jdk原生的类是谁加载的?

不会(我一开始都没听懂他在问什么,还让面试官重复了一下问题。这边直接把面试官唐笑了,我自己也没绷住笑了。面试官然后和我提到了Extension ClassLoaderAppClassLoader

ps:查了一下,外部引入的jar包是由最底层的 应用程序类加载器(AppClassLoader)加载的,而 JDK 原生的类是通过顶层的启动类加载器(BootStrap ClassLoader)加载。

Java 并发

1)线程池有哪些常用的参数?

答了7个参数:核心线程数、总线程数(最大线程数)、阻塞队列、时间单位、存活时间、拒绝策略、线程工厂

2)其中的拒绝策略有哪几种?

这边完全忘了,然后答了有一种是直接抛出异常(实际上是AbortPolicy:直接抛出一个任务被线程池拒绝的异常)

ps:有四种预置的拒绝策略:CallerRunsPolicy:使用线程池的调用者所在的线程去执行被拒绝的任务AbortPolicy:直接抛出一个任务被线程池拒绝的异常DiscardPolicy:不做任何处理,静默去拒绝提交的任务DiscardOldestPolicy:抛弃最老的任务,然后执行该任务

3)如果核心线程数已经占满了,如果来了新的任务他会怎么处理?

这边答的一坨,说如果核心线程数小于最大线程数,会创建救急线程去处理。(严重答错)

ps:实际上是会先扔到阻塞队列里等待,如果阻塞队列也满了,线程数 < 最大线程数,会创建非核心线程(救急线程)来处理;否则如果最大线程数也满了,就执行拒绝策略)

4)AQS是如何实现的?可以介绍一下吗?

答了AQS是叫Abstract Queued Synchronizer,它底层是有一个status去记录是否被锁进行占用。这个变量是能够保证同一个线程可重入的。其次它里面有个队列,底层是用双向链表去实现。然后又提了一下后续线程唤醒策略决定锁是否公平

ps:复习了一下,AQS实现核心分为三个部分:同步状态(State)、CLH队列(等待队列)、原子操作(CAS),它实际上是一个同步器框架。CLH队列的头指针指向当前持有锁的线程节点,如果线程获取锁失败,会被封装为一个Node,插入到等待队列的末尾,随后线程被阻塞。

对于独占模式(比如ReentrantLock)的实现流程

  • 尝试获取锁(acquire):先尝试CAS抢锁(线程调用 tryAcquire()去尝试原子性修改state),如果成功,那么当前这个线程是独占线程。如果失败,要么是重入(state+= 1),不是重入的话进入等待队列。如果线程阻塞,会检查是否是head.next,如果是,会尝试继续抢锁,防止“假唤醒”。抢锁失败,线程会被park直至唤醒。
  • 释放锁(release): 首先去调用tryRelease(int arg),也就是 state -= arg。如果state减到0,表示锁完全释放。随后唤醒后继节点,被唤醒的后继节点也会进行抢锁,防止“假唤醒。

5)ThreadLocal 它内部是一个什么样的数据结构?

这边答了Map(也许直接答ThreadLocalMap更好一点?),然后提到了弱引用和内存泄漏的问题,需要在最后的finally中调用remove()方法

ps:实际上,ThreadLocal的底层实现是依靠Thread类内部维护的一个ThreadLocalMap

6)那么它的key是啥?value是啥?

这边答了key是线程的id,value是存储的变量(答的不太对)

ps:key是ThreadLocal对象本身,value是我们要存储的变量副本。对于弱引用问题:ThreadLocalMap中的key是弱引用,如果ThreadLocal外部没有强引用,GC时会被回收,导致Map中出现key为null但是value还在的情况,造成内存泄漏。所以,使用完之后务必调用remove()方法。

MySQL

1)事务隔离级别有哪些?MySQL默认是哪个?

答了 uncommitted read、committed read、repeatable read、serializable,其中MySQL默认是Innodb引擎,也就是可重复读。

2)介绍一下索引的数据结构

答使用B+树,然后开始吟唱B+树特性(范围查询、只有叶子结点存储数据信息、矮胖树)

3)像我们查询条件里的 like 语句,是执行索引的吗?

这边答了看情况,或者说是左模糊匹配,此时就会发生索引失效。如果在最右边的话,那么还是能够进行部分索引查询。

ps:答的应该没错,这边最好再提一下MySQL的B+树中的最左前缀原则

4)什么是联合索引,这个了解吗?

答联合索引是多个索引并行,首个字段会有序,之后的字段在前者索引限定的区间内各自有序(此处答的还是欠妥)

ps:联合索引就是多列索引,也就是在数据库表的多个字段上创建的一个索引。符合多字段排序和最左前缀原则。

5)SQL 题目:统计最高分的学生(两张表,一张包含student_id、course_id、score,还一张包括stundent_id、student_name,然后要求把总分最高的那个学生的student_name和总分返回)

这个题不是很难,面试官给题的时候也说很简单的一道题。写了个子查询搞掉了,但是还是出了点小错,一开始把SUM写成COUNT,还忘了写order by,后面补回来了。

反问

1)关于此次面试中我的改进之处,当然有一点很重要,是我刚刚那个算法手撕没写出来

面试官告诫我要继续多练练算法,就是有一些很难的算法倒还好,但是像反转链表这种肯定是要很快的把它写出来不出错。

2)后续技术栈学习和关于项目学习的建议,有没有必要再学一下ES之类的

面试官说这几个项目其实挺全的(前后写过的外卖、点评和现在正在学的12306火车购票项目),简历上的技术栈也基本覆盖了要求。如果可以的话,再加一个Kafka。建议是现在把那些现有的基础的再再打牢一点。因为到时候你像秋招或春招面试的时候,他不会太要求你会多少框架,但是那些技术底层实现他们是一定会考察的。你的项目我觉得现在面试,就是实习这个阶段而言已经够了;那如果面向明年的暑期的话,也是足够的。对,因为本身实习生就没有项目,因为大部分都是在一些视频课程上做的一些实践,对吧? 然后就主要针对是针对项目的话,主要就是看你们那个实践的过程中的一些思考,就是有一些问题是不是真正理解了。 然后至于那些工具和框架,其实不用看着那么多。当然你像常用的这个SpringBoot框架和MySQL、Redis,这个是越熟悉越好。像ES那种的话,它属于是扩展科目了。对,这不要求这个阶段一定要会的。

3)面试流程

日常实习的话是两轮技术面+一轮hr面

最后真的很感激这位面试官,给出的建议全面周到,而且相当客观真实。他在提问的时候很和蔼客气,很nice。之后自己一定要好好继续学下去,明年暑期争取能去美团(先幻想一波)

#如何判断面试是否凉了##美团求职进展汇总##美团##发面经攒人品##面试问题记录#
面经总结回顾 文章被收录于专栏

本专栏用于记录我的日常实习、暑期实习和秋招中面经的记录、反思和总结

全部评论
哥一起加油,我们都会有offer的
点赞 回复 分享
发布于 今天 00:07 广东
加油
点赞 回复 分享
发布于 昨天 22:37 江苏
刚刚又倒回去看了一下回放,我真是蠢。那个翻转链表的子函数甚至返回值返回另一个变量这题都过了,好不容易有个面试机会结果栽在这个小阴沟里。我也整不明白为什么那天晚上写算法的时候会那么紧张,可恶的期末考试
点赞 回复 分享
发布于 昨天 22:22 吉林
加油
点赞 回复 分享
发布于 昨天 20:54 北京
兄弟这个是在官网投的还是ssob上投的呀
点赞 回复 分享
发布于 昨天 20:46 重庆
哥面的哪个部门呀
点赞 回复 分享
发布于 昨天 19:45 黑龙江
加油兄弟
点赞 回复 分享
发布于 昨天 19:40 湖南

相关推荐

给🐭🐭个面试机会...:我擦seed✌🏻
点赞 评论 收藏
分享
评论
8
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务