泪崩,中厂一面也要输了。。。

分享过很多小厂和大厂的后端面经,这次来分享互联网中厂的面经,面试难度也是刚好介于大厂和小厂之间。

除了技术问题之外,互联网中厂面试环节也需要手撕算法,所以想冲中大厂的同学们,算法不能拉下。

这次分享 58 同城的Java后端凉经,问题不算特别多,15 个左右,再加上 1 个算法题,大家看看难度如何?

图片

考察的知识点;

  • Java:HashMap、ConcurrentHashMap、volatile、sychronized、线程池

  • 网络:TCP三次握手、四次挥手、netstat 命令

  • mysql:B+树和B树、聚簇索引和非聚簇索引

  • 排序算法:快排时间复杂度、冒泡排序时间复杂度

  • 手撕算法:单链表删除重复元素

Java 并发

HashMap和ConcurrentHashMap区别是什么?

HashMap 不是线程安全的,ConcurrentHashMap是线程安全的。

HashMap 底层实现

  • 在 JDK 1.7 版本之前, HashMap 数据结构是数组和链表,HashMap通过哈希算法将元素的键(Key)映射到数组中的槽位(Bucket)。如果多个键映射到同一个槽位,它们会以链表的形式存储在同一个槽位上,因为链表的查询时间是O(n),所以冲突很严重,一个索引上的链表非常长,效率就很低了。

图片

  • 所以在 JDK 1.8 版本的时候做了优化,当一个链表的长度超过8的时候就转换数据结构,不再使用链表存储,而是使用红黑树,查找时使用红黑树,时间复杂度O(log n),可以提高查询性能,但是在数量较少时,即数量小于6时,会将红黑树转换回链表。

图片

ConcurrentHashMap 底层实现

  • 在 JDK 1.7 中它使用的是数组加链表的形式实现的,而数组又分为:大数组 Segment 和小数组 HashEntry。Segment 是一种可重入锁(ReentrantLock),在 ConcurrentHashMap 里扮演锁的角色;HashEntry 则用于存储键值对数据。一个 ConcurrentHashMap 里包含一个 Segment 数组,一个 Segment 里包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素。简单理解就是,ConcurrentHashMap 是一个 Segment 数组,Segment 通过继承 ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全。

图片

  • JDK 1.8 也引入了红黑树,优化了之前的固定链表,那么当数据量比较大的时候,查询性能也得到了很大的提升,从之前的 O(n) 优化到了 O(logn) 的时间复杂度。ConcurrentHashMap 主要通过 volatile + CAS 或者 synchronized 来实现的线程安全的,ConcurrentHashMap通过对头结点加锁来保证线程安全的,锁的粒度相比 Segment 来说更小了,发生冲突和加锁的频率降低了,并发操作的性能就提高了。

图片

CAS和sychronized分别用于ConcurrentHashMap什么场景?

添加元素时首先会判断容器是否为空:

  • 如果为空则使用  volatile  加  CAS  来初始化

  • 如果容器不为空,则根据存储的元素计算该位置是否为空。

    • 如果根据存储的元素计算结果为空,则利用  CAS  设置该节点;

    • 如果根据存储的元素计算结果不为空,则使用 synchronized  ,然后,遍历桶中的数据,并替换或新增节点到桶中,最后再判断是否需要转为红黑树,这样就能保证并发访问时的线程安全了。

volatile和sychronized比较,原理?

Synchronized解决了多线程访问共享资源时可能出现的竞态条件和数据不一致的问题,保证了线程安全性。Volatile解决

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值