上午坐在图书馆前草坪的椅子上看《Netty权威指南》,差不多到了饭点,正准备起身去食堂吃饭,这时迎来一个突
如其来的电话,上面显示:“浙江-杭州”。(因此前并未约面试,不知这就是阿里巴巴菜鸟网络的面试电话)
先介绍一下你自己吧
略……
你做的项目中,你觉得最有挑战的一件事是什么事啊?
我觉得最有挑战的是一次商品搜索功能的实现,当时本来是准备用 Solr 做的,但是当时的项目用的是
SpringBoot ,之前学Solr的时候是用 Solr 是和 Spring 整合,我用 SpringBoot 集成 Solr 发现版本差
异很大,API也不用了,然后 Solr 初始配置繁琐,当时就想换一个搜索框架。然后我听说
Elasticsearch 挺好用的,于是就从0开始研究它的API,最后实现了商品搜索必需的一些功能,如关键
字检索、结果高亮、聚合等。虽然我对ES的底层了解不多,但这一次是我独立对一个陌生框架的学习并实
现了需要的基本功能。
就是你觉得用ES替换Solr比较有技术含量是吧?
不是的。只是说有这么一个难题吧,现在Solr没办法用了,要逃离舒适区接触一个陌生的ES,从无到有的
将商品检索功能实现,不说有多么高性能,起码实现了基本的功能。
ES的源码,你有看过吗?
emmm……,没有。
在自己的简历中写一些不知底层原理没有读过源码的花里胡哨的框架技术等于给自己埋坑
Java的源码有没有看过?
Java的源码,多线程的看过一些,集合的也看过一些。
那你给我讲一下 ConcurrentHashMap 和 HashMap 的区别。
ConcurrentHashMap 的核心思想就是降低锁粒度以提高并发性能。 HashMap 不是线程安全的,
HashTable 虽然是线程安全的,但其相对于 HashMap 来说,只是简单地将每个访问集合的方法都加了一
个 synchronized 关键字,也就是说任何访问集合的线程都需要先获取集合对象对应的锁,这样的话同一
时刻只能有一个线程操作Map,并发性能弱,如果并发线程较多还会引起多次上下文切换。而
ConcurrentHashMap 采用锁分段的技术,默认在集合内部维护了16把锁,每几个 Bucket 作为一个组,
每个组对应一把锁,这样最多就能支持16个线程同时访问Map了。
每个Bucket对应一把锁是吧?
我记得好像是一把锁对应几个Bucket
HashMap 在并发场景下,它不安全的点是哪里?
就是可能会造成Bucket中的链表形成环形链表,导致后续的Map.get操作可能会造成无限循环,导致CPU
的100%占用。
仔细说一下形成环形链表的过程。(解析参考)
HashMap 在元素个数到达阀值(容量x复杂引子)后会进行扩容,首先新建一个扩容后的空Map,然后遍
历Entry将其Rehash到新的Map上。Rehash(对应方法 transfer )中有一行代码是 Entry next =
e.next ,其中 e 是当前遍历到的Entry。假设现在有两个线程A、B都在Rehash,B遍历到Entry3刚得到
next(比如Entry2)时就消耗完时间片被挂起了,此时对于B来说 e=Entry3,next=Entry2 。这时A抢到
CPU执行权,畅通无阻的执行完了Rehash操作: