记一次腾讯面试经历(没通过的经历)

7,958 阅读7分钟

腾讯面试定在了晚上七点,并且腾讯会议视频面试,自己在周三接到的面试邀请,面试官添加了微信联系定了时间。初定周四,后续因面试官有事改到周五,面试官交流很客气。

这次面试自己也有问题, 没有调试好自己的电脑,因此当说到面试过程中如何写代码时我就知道需要考察算法代码的。但是可能面试官也不想再麻烦直接就开始了。

1、自我介绍,

自我介绍自己按照工作经历以及离职原因、所掌握技术栈、工作之余的兴趣三个方面说了下。这里面试官问了我第二份工作的地点,如实回答外包。

2、String、StringBuffer、StringBuilder的区别?

这里我介绍了String的final的特性,然后说了StringBuffer是线程安全的,String、StringBuilder是非线程安全的。

3、Java的内存模型

这个问题先前复习过,这里从主内存以及线程的工作内存说了下,另外也说了主内存与工作内存的交互操作,例如Read、Write、Load、Store.....实现主内存与工作内存的交互,这里也提了一下volatile的内存屏障。

4、对Synchronized、CAS、volatile有什么认识?大致介绍下?

先说了CAS的问题,CAS说了通过Unsafe类来实现的,Unsafe类中的compareAndSet方法提供CAS特性,并且这是一种乐观锁的形式,通过比较与交换实现数据的更改,同时保证线程安全,但是这种线程安全会存在性能问题。

synchronized讲了底层的实现通过对象中的监视器来实现,并且对象加锁标志是通过对象头中的markword来实现的,每次对markword的对象标志设置加锁解锁。同时synchronized可以使用在方法和代码块中,使用在代码块中是通过monitorentermonitorexit来实现加锁、释放锁的过程,使用在方法中通过ACC_SYNCHRONIZED来实现加锁标志(这个锁的标志在对象头中存储的)。

并且synchronized还是一个可重入锁,也就是当一个线程获取了锁,当它再次获取锁时只需要判断markword中的当前锁线程是否是当前线程即可,不需要再进行加锁的过程,这里也提到了synchronized锁升级的问题,说了一下锁从轻量级锁到重量级锁的升级,这里忘记了偏向锁。(补充:首先偏向锁,偏向锁在对象中也是通过markword中的一个标志位来实现的,如果一个线程获取了锁,在markword中就会存储该线程的id,当线程再次操作该对象,会判断偏向的线程是否是当前线程,如果是则不需要再进行加锁的过程。轻量级锁而言,既然是轻量级锁,那么就不能进行线程的阻塞,所以synchronized实现轻量级锁是通过乐观锁的观念来实现的,如果一个线程获取不到锁,不会让线程阻塞,只会让线程做自旋操作,如果其它线程释放了锁,那么自旋的线程就可以获取锁了,但是不能一直让线程做自旋,这样会一直占用cpu资源,所以如果自旋十次还获取不到锁,那么轻量级锁就会升级为重量级锁)

最后讲了一下volatile的问题,volatile从可见性和禁止重排序两个方面讲了,可见性方面从数据失效说了下,如果一个线程操作一个共享变量,那么该共享变量在其它线程的工作内存中就失效,需要从主内存中重新获取。禁止重排序方面从内存屏障说了下,提了下load和store的操作,但是具体的没有展开说。(当时忘记了!)

5、synchronized锁优化了解吗?

这里说了锁升级的过程,具体的优化偏向锁、自旋锁、轻量级锁、重量级锁忘记了!当时没说

6、hashMap、hashTable、concurrentHashMap的区别?

这三个我先说了数据结构,都是key-value的形式,然后说了hashMap是非线程安全的,hashTable、concurrentHashMap是线程安全的,同时hashMap展开说了下里面的扩容时进行rehash的操作,hashMap如何避免rehash的问题,通过扩容后的长度-1和hashcode做与操作,进行判断是否需要进行rehash。hashTable说了保证线程安全是通过synchronized来实现的,concurrentHashMap说了下自己的理解,保证线程安全是通过对一个桶位加锁。

7、JVM的垃圾收集器

垃圾收集器里面我说了Serial收集器,是stop the world的形式,需要停止其它工作,直到垃圾收集结束。是通过标记-清除算法实现的。

ParNew收集器,支持多线程,通过复制算法实现的。

CMS收集器,Hotspot虚拟机的默认收集器,通过分代收集算法实现的。

8、redis的跳跃表了解吗?说下原理?

redis的跳跃表这里我通过自己的理解说了下,我将跳跃表看成一座座大楼,第一座大楼与后续的大楼做了指向,也就是第三层指向第二座大楼,第四层指向第三座大楼,依次类推,最多是32层,并且数据在跳跃表中是升序的,因此当查询数字3时,可以从第一座楼指向第三座楼的指针可以得到3,而不需要进行遍历。或者二分法查找,避免了二叉树时间复杂度会变成O(n)的情况。

9、计算机网络熟悉吗?说下TCP、UDP的区别?

这里说了下TCP面向连接的,UDP不面向连接,同时TCP是可靠性传输,UDP不是可靠传输。

10、那你说一下TCP如何保证可靠传输?

这个问题自己回答的不是太好,从说了下拥塞控制、滑动窗口、超时重传、等待确认机制。其它记得不是很清楚没说。

11、TCP的粘包了解吗?说下

没怎么了解过,后续我可以学习下!

12、LRU的实现原理?

把LRU的get、put方法介绍了一下流程。

13、LRU的数据结构如何设计?

当时忘记了,紧张的要死。

14、说下自己的项目?具体做了哪些东西,从细节上说?

从项目说,然后说了具体做了什么?如何实现的?

说了项目使用的技术栈、以及项目的架构,最后说了自己的做的功能的具体实现,自我感觉这里写的特别乱。

15、你有什么要问我的吗?

我:请问公司是做什么业务的?

面试官:xxxxx

我:通过刚才的面试,您觉得我在技术方面哪些还需要提升的?

面试官:说了我计算机网络方面不熟练,后续要再学习,说我LRU理解不够透彻,然后说我在项目中并没有做特别有深度的东西,还需要加深。

整个面试市场37分钟,我已经知道面试不理想了,因为还没考代码就提前结束了面试。整体问的问题都很基础,但是自己答的还是不太理想,一方面掌握的不够牢固,另一方面太过紧张,后续再调整,还是很感谢有这样的机会接受一次面试。

第二天接到了面试不通过的短信,不过也没什么,再继续努力,自己欠缺的还是太多,也算是一份经历。后续继续加油!

面试官很nice的,首先很客气,而且给提出后续需要加强的意见,这是很感谢的,只能说能力还不够,没什么沮丧和失望的。自信还是有的,再继续努力吧!