面试总结2022年04月12日10:37:54

书中人 2022年04月12日 1,596次浏览

自我介绍

单例设计模式(双重检查锁)

public class SingletonMode {
  private static volatile SingletonMode singletonMode;

  private SingletonMode() {
  }

  public static SingletonMode getInstance() {
      if (singletonMode == null) {
          synchronized (SingletonMode.class) {
              if (singletonMode == null) {
                  singletonMode = new SingletonMode();
              }
          }
      }
      return singletonMode;
  }
}

优化执行慢的接口,优化思路

首先按照常理,接口慢一般分为代码逻辑多的业务慢和数据库慢:首先我们要确定是那块代码, 那条sql出现了问题。然后在逐个解决。我们可以采用spring提供的stopwatch进行关键节点大标, 然后进行压测多次,统计接口不同位置的执行时间,找出最慢的那块代码, 然后排查是不是代码有问题,出现了多次循环,伪死锁等,然后处理代码,如果不是, 那就排查是不是sql慢,根据sql优化规范进行优化,比如查看执行计划,创建合理的索引等。

微信二维码登录

微信二维码登录没有做过:分析 首先二维码内部其实是一个url这个明确。而且这个url是由服务端首先生成发送给页面。 而且是有客户端发起的,所以会携带了客户端的一些信息, 在服务端进行处理后加密生成一个带有当前客户信息状态的临时二维码下发给用户, 当然这个状态会存储到服务器,服务器端同时在轮训这个状态。 等待用户扫描了二维码后,获取用户本地登录信息token, 并上传到服务端后,服务状态检测到变更后, 将用户扫描后上传的token信息解析和数据库用户信息进行比对, 如果正确就是返回重新生成一个临时token给用户, 用户确认登录后,这个token验证进行存储到客户端和服务端, 之后所有请求都使用这个token进行。

多线程-> 几种状态,状态之间切换,sleep和wate区别

1. 新建状态(New): 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
3. 运行状态(Running): 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
4. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
(02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
(03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

sleep和wait区别

1, sleep 是thread的方法,wait是object的方法 2,sleep不释放锁,不释放cpu,wait释放锁,释放cpu 3,sleep到设计时间自动醒来,wait需要被notify和notifyAll在同步控制方法或者同步控制块里面使用并唤醒。

synchronized和reentrantlock的区别,reentrantlock构造器有一个true和false,代表什么意思?

synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定, 而且在代码执行时出现异常,JVM会自动释放锁定 但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中 在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态; 但是在jdk不断给sync优化的过程,现在性能上也基本差不多,synchronized优化了一个锁升级的过程,偏向锁 > 轻量级锁 > 重量级锁 整个过程是不可逆的 reentrantlock的可重入锁,构造器默认是false,非公平锁,就是如果没有抢到锁,和其他线程一起进入tryAcquire等待,如果所释放了,stat==0 ,则不用判断队列中是否有线程,就去抢锁。但是公平锁就会乖乖排队,不会进行抢锁如果队列中有线程的情况。

threadlocal用过没,项目中那些地方用了?

threadlocal在项目中用来做接口请求中的用户信息存储,gateway拦击器,登录请求后将token存储到浏览器,每次用户请求的时候都会带token到后端,后端gt拦截器将其拦截并解析后,存储到threadlocal中,这样以后不管那块业务逻辑需要当先用户信息,都可以随时随地从threadlocal获取,springcloud项目透传的时候,通过threadlocal直接将用户登录信息透传过去,定义到比如feig的请求拦截器RequestInterceptor实现类中作统一权限处理。(RequestContextHolder.getRequestAttributes() spring包装的一个threadlocal。
image-1649731668120

linkedHashMap和TreeMap的区别

linkedHashMap是根据用户put的顺序进行遍历(也就是保证插入和读取有序),而TreeMap是利用比较器进行排序(比较有序)。

MySQL

覆盖索引:查询字段全部在索引中可以找到,不需要回表查询的都成为覆盖索引,索引覆盖索引肯定存储了列的值;
聚簇索引:一般使用唯一主键作为聚簇索引,用来建立索引树,如果没有索引则采用非空唯一字段作为主键,如果也没有则隐式生成一个。

SpringMVC执行流程

image-1649923203319
image-1649923491459

#redis主从同步 ,全量不同和增量同步
redis主从同步
https://blog.csdn.net/denghonghao/article/details/82108770

#canal同步问题
canal会不会丢数据?
Canal正常情况下不会丢数据,但是比如集群节点失效,重启,Consumer关闭等也是会丢失数据的,可能有一下几种可能:

  1. zk的数据可靠性或者安全性被破坏,比如zk数据丢失,zk的数据被篡改,特别是有关position的值
  2. mysql的binlog非正常运维,比如binlog迁移,重命名,丢失等。
  3. 雀环mysql源,比如从m1实例,切换到m2实例,而且m1和m2可能binlog数据存的不一致。
  4. Consumer端的ack时机不对,调用的是get(),而不是getWithoutAck(),那么此时有可能尚未完全消费,就已经ack了,那么此时有异常或者Consumer实例失效,则可能到值小时丢失,我们需要在ack时机上保证“at lease once”

#Canal延迟很大的原因是什么?

  1. 如果批量的insert update delete,都有可能导致大量的binlog产生,会家具master与slave之间的数据同步延迟(频繁写入)。
  2. canal是根据数据流的pipeline,“master-slave-canal-consumer”每个环节都需要耗时,而且整个管道都是单线程,串行,阻塞时
  3. 如果canal节点zk的网络连通性不畅,将会导致canal几圈出狱动荡状态,大量的时间消耗在zk状态监测和维护上,而无法对外提供正常服务,包括不能顺畅的dump数据库数据。

#递归可以递归多少次
递归理论上可以递归无限次,但是限于内存栈的大小,到一定程度会栈溢出,可以通过-Xss配置栈大小。