技术一面

Java线程安全和线程非安全的类举例

  • 线程安全。 Vector,ConcurrentHashMap
  • 线程非安全。ArrayList,HashMap

HashTable和CurrentMap区别

HashTable使用Synchronized关键字进行同步控制,CurrentHashMap使用分段锁进行同步控制,CurrentHashMap性能更好

volatile作用及原理

  • 可见性。可见性的解读为一个行程修改的状态对另一个线程是可见的,一个线程修改的结果,另一个线程马上就能看到。volatile关键字会强制将修改的值立即写入主存,一个线程修改volatile修饰变量会导致其他线程的工作内存中缓存失效(从硬件层面上来看就是讲CPU中的L1或L2缓存中对应的缓存行无效)
  • 禁止指令重排。保证对volatile变量进行读写时,在其前面的操作的更改肯定全部进行,且结果对后面的操作可见,其后面的操作肯定还没有进行

在进行指令优化时,不能把volatile变量前面的语句放到其后面执行,也不能把volatile变量后面的语句放到其前面执行

volatile内存语义的实现与内存屏障有关,编译器在生成字节码时,会在指令序列插入内存屏障,内存屏障是一组处理器指令,先于这个内存屏障的指令必须先执行,后于这个内存屏障的指令必须后执行,在读指令前插入读屏障,可以让高速缓存中的数据失效,重新从主内存中加载数据,在写指令后插入写屏障,能让写入缓存的最新数据写回主内存。

HttpRequest内容

  • 请求行。 请求方法(get/post),请求URL,HTTP协议及版本
  • 请求头。 Accept/Cookie/Connection之类
  • 请求体。具体请求内容

请求头和请求体之间通过换行分隔

ThreadLocal

  • 原理 Thread维护了ThreadLocalMap变量,ThreadLocalMap是ThreadLocal的内部类。ThreadLocalMap的key是ThreadLocal的引用,value是要存储的对象
  • 应用场景 ThreadLocal实现当前线程的操作都使用同一个数据库Connection

线程安全的原子类

AtomicInteger/AtomicLong

CAS原理

compare and set,比较旧值是否相同,然后设置新值

线程实现方案有哪些

实现Runnable/Callable接口,继承Thread,使用线程池创建

线程的状态有哪些

new/runnable/blocked/Time waiting/waiting/Terminated

如何理解分布式事务

随着微服务架构的普及,一个大型业务系统往往由若干个子系统构成,这些子系统又拥有各自独立的数据库,一个业务往往由多个子系统共同完成,这些操作需要在一个事务中完成。

  • 实现原理
  • 两阶段提交协议2PC
  • 三阶段提交协议3PC

分布式锁如何实现

  • Mysql
  • Zookeeper
  • Redis。使用setNx resourceName value,过期时间控制`set resourceName value ex 5 nx ]

微服务概念

  • x,y,z轴切分,服务发现,服务治理

Join和union区别

join是联表查询,union是组合查询,组合查询可以将两个select语句(结果列数相同且字段类型相似)的结果去并集去重,可以使用union all去重。

数据库隔离级别

  • 读未提交
  • 读已提交
  • 可重复度
  • 串行化

数据库可重复读的实现

三级封锁协议,要求读取A数据时必须加S锁,指导事务结束后才能释放S锁,因为读A时,其他事务不能对A加X锁,从而避免了在读的期间数据发生变化

联合索引ABC,对ABC排列组合,哪些用到了索引

根据数据库最左匹配原则,A,AB,ABC的查询用到了联合索引。

Spring AOP原理

Spring AOP主要是通过JDK动态代理和Cglib动态代理实现,将非业务代码通过切面的方式编织到业务代码中去

Spring事务传播机制

  • PROPAGATION_REQUIRED 支持当前事务,如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。
  • PROPAGATION_SUPPORTS 如果上下文存在事务,则支持事务加入事务,如果没有事务,则使用非事务方式执行
  • PROPAGATION_MANDATORY 要求上下文中必须存在事务,这个方法不能被单独执行,必须被事务方法调用,否则抛出异常
  • PROPAGATION_REQUIRES_NEW 每次都会新建一个事务,并且同时将上下文中的事务挂起。AB均申明事务,如果A失败回滚,B是不会回滚的,因为两个在不同事务中,如果B失败回归,A中捕获异常,事务A仍会提交
  • PROPAGATION_NOT_SUPPORTED 不支持事务,如果存在事务则事务被挂起,执行当前逻辑后恢复事务,可以帮助缩小事务粒度
  • PROPAGTION_NEVER 逻辑不能在事务中运行,一旦有事务,则抛出异常
  • PROPAGATION_NESTED PROPAGATION_NESTED为父子事务,实际上是借助jdbc的savepoint实现的,属于同一个事务。PROPAGATION_NESTED的回滚可以总结为,子事务回滚到savepoint,父事务可选择性回滚或者不不滚;父事务回滚子事务一定回滚。

REQUIRED和SUPPORTS区别,A方法调用B方法,A未申明事务,B申明事务,REQUIRED会为B新建事务,SUPPORTS则以非事务方式执行B

技术二面

讲项目

谈到了排队分流引擎

一致性Hash算法,如何保证散列均匀

机器数量不多的情况下,可以使用虚拟节点

如何防止数据库击穿和数据库雪崩

  • 使用互斥锁(mutex key) 缓存失效,使用分布式互斥锁,单线程去load db并设置缓存,其他线程重试get方法
  • 流控

JDK锁

  • Synchronized
  • ReentrantLock

AQS

  • state 状态计数
  • queue 线程排队