技术岗面试题小结(二)
技术岗面试题小结(二)
研发岗的面试问题可能不会局限于某个编程语言或者某个技术栈,有时候也会去问一些比较杂项的东西,所以这里单开一个系列来汇总这些杂项题目。可能会包括一些智力题和应用题
1.CAS算法的缺点
ABA问题,数据经过多次修改回到了初始值,此时使用CAS算法无法判断是否被修改 解决方案是引入版本号数据,案例有Java的AtomicStampedReference类
高竞争开销,反复重试的情况下CPU开销大,解决方案是引入退出机制,设置重试次数上限,或避免使用乐观锁
功能受限,CAS只能保证单值的操作原子性
2.包装类Integer,如果值都是100,用==判断,它们是否是相等的?
相等,虽然Integer对象比较的是地址,但值位于-128到127之间时会直接使用常量池中对应的缓存对象,因此两个值为100的Integer对象实则引用的是同一个缓存对象
3.CPU核心数量与线程池数量的关系
CPU密集型应用(算法等):线程池大小设置为N+1左右
IO密集型应用(IO,网络等):线程池大小设置为2N+1左右
4.一根绳子随机切3段,能够构成三角形的概率是多大
概率为1/4,需要列举不等式组来通过图像解答,如下: 记三段绳子长为x,y,1-x-y,约束条件为:
画出图像可以发现取值范围占定义域的四分之一
5.KMP算法
KMP是高效的字符串匹配算法,避免了传统字符串匹配的繁杂回溯操作 记原字符串为str,其索引为,需匹配字符串为模式字符串pat,其索引为
要求即为寻找txt中是否包含pat
同时提出一个最大匹配长度的概念,这个指的是子串前缀与后缀相同部分的最大长度
使用next[]数组来储存模式字符串每一个子串(均从头开始)的最大匹配长度,next[i]意味着匹配失败时需要回退到的位置,而无需回溯。next的算法如下:
next[0]=0;
for(int i=1;i<pat.length();i++){
if(pat.chatAt(i)==pat.charAt(next[i-1])){
next[i]=next[i-1]+1;
}else{
next[i]=0;
}
}
然后是正式匹配操作,和均从开始进行匹配。 若匹配成功,即str[i]==pat[j],和均+1 若匹配失败,保持不变,回退到next[j-1]的位置,继续匹配str[i]和pat[next[j-1]]
算法如下:
int i=0,j=0;
while(i<str.length()){
if(str.charAt[i]==pat.charAt[j]){
i++;
j++;
}else{
j=next[j-1];
}
if(j==pat.length())return true;
}
return false;
6.SQL语句优化
- 不使用 * 而使用具体字段,节省资源
//优化前
SELECT * FROM user;
//优化后
SELECT id, name FROM user;
- 对排重要求不高的情况合并查询结果用union all 代替union
//优化前
(SELECT * FROM user WHERE id=1)
UNION
(SELECT * FROM user WHERE id=2);
//优化后
(SELECT * FROM user WHERE id=1)
UNION ALL
(SELECT * FROM user WHERE id=2);
- 小表驱动大表,in左大右小,exists左小右大
- 批量操作,避免多次请求数据库
- 使用limit限制查询数据数量
- 分表分库,分页查询
- 联表查询时减少join使用数量
7.MySQL和Redis数据一致性的解决方案
MySQL作为数据库,Redis作为缓存
- 双写,业务代码中同时对两个数据库进行更新(先MySQL后Redis),但程序网络有问题的情况下无法保证双写一致性
- 消息队列,向双写业务代码中引入消息队列,监听数据库变更事件,异步更新数据库
- 实时同步,MySQL数据发生变化时,通过触发器、消息队列等方式通知Redis更新
8.MySQL的行锁
MySQL自动根据需要锁定事务需要修改的数据行
- 记录锁:锁定被操作的数据行,保护记录不被其他事务修改,其中排他锁(X锁)不能读写,共享锁(S锁)不能修改
- 间隙锁:锁定范围而不包括范围内数据,阻止其他事务在该范围内插入数据,防止幻读(两次相同查询在事务执行时,第二次查询返回了新插入行)
- 临键锁:锁定范围内的记录
9.Redis宕机怎么办
及时重启Redis服务(Redis守护进程),检查日志文件和配置文件,保持对Redis性能的监控。 根据宕机原因对服务配置进行修改和优化,例如优化内存使用率,提高最大连接数。
10.MyBatis的#和$有什么区别
${}是字符串替换,会将参数值拼接到SQL中,存在SQL注入的风险,#{}可以防止SQL注入
11.HashMap与泊松分布
HashMap底层从链表变为红黑树的阈值为8,由加载因子loadFactory=0.75和泊松分布决定(红黑树退化为链表的阈值为6)
随机hashCode的算法下,通过泊松分布式计算长度为8时发生哈希碰撞的概率约为亿分之六,大于8的情况下可以视为几乎不发生碰撞
12.Redis的缓存击穿、缓存穿透、缓存雪崩
(1)缓存击穿: 用户查询数据在缓存中不存在,在数据库中存在,需要访问数据库。主要针对某一热点key失效,导致大量访问需要访问数据库,导致数据库负载瞬间增加
解决方案:热点key永不过期或定时更新过期时间,互斥锁(首次访问数据库加锁)
(2)缓存穿透: 查询数据时,缓存未命中,访问数据库时也未查询到数据造成查询失败,最终返回空对象。大量该类型查询会令MySQL增压、甚至崩溃。
导致原因:可能是数据被删除或恶意攻击。
解决方案:缓存空对象,业务逻辑筛查,黑名单,布隆过滤器
(3)缓存雪崩: 大规模key过期导致的缓存击穿或Redis宕机,导致海量请求进入数据库
解决方案:设置有效期均匀分布,大量请求前数据预热,增强Redis服务可用性
13.布隆过滤器
一种概率型数据结构,用于判断一个元素是否属于某个集合,基本结构是一个位数组
通过哈希算法,在插入数据时将对应索引位置的位设置为1。在查询时,通过哈希查询对应位上的值,若为1,则可能存在该集合中,若为0,则不可能存在于该集合中
因为哈希碰撞,可能导致不同插入映射到了同一位上,出现 假阳(误报) 情况,但不会出现 假阴(漏报) 的情况