跳至主要內容

技术岗面试题小结(二)

Unisky大约 6 分钟学习面试

技术岗面试题小结(二)

研发岗的面试问题可能不会局限于某个编程语言或者某个技术栈,有时候也会去问一些比较杂项的东西,所以这里单开一个系列来汇总这些杂项题目。可能会包括一些智力题和应用题

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,约束条件为:

  • 0<x,y<0.50<x,y<0.5
  • x+y>1xyx+y>1-x-y
  • x+1xy>yx+1-x-y>y
  • y+1xy>xy+1-x-y>x

画出图像可以发现取值范围占定义域的四分之一

5.KMP算法

KMP是高效的字符串匹配算法,避免了传统字符串匹配的繁杂回溯操作 记原字符串为str,其索引为ii,需匹配字符串为模式字符串pat,其索引为jj

要求即为寻找txt中是否包含pat

同时提出一个最大匹配长度的概念,这个指的是子串前缀与后缀相同部分的最大长度

使用next[]数组来储存模式字符串每一个子串(均从头开始)的最大匹配长度,next[i]意味着匹配失败时jj需要回退到的位置,而ii无需回溯。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;
  }
}

然后是正式匹配操作,iijj均从00开始进行匹配。 若匹配成功,即str[i]==pat[j]iijj均+1 若匹配失败,ii保持不变,jj回退到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,则不可能存在于该集合中

因为哈希碰撞,可能导致不同插入映射到了同一位上,出现 假阳(误报) 情况,但不会出现 假阴(漏报) 的情况