面试题day25
-
项目如何限流?
-
添加购物车时,数据库层面是如何操作的?
-
知道接口的幂等性和非幂等性吗?
-
项目里面有没有考虑幂等性?
-
自定义线程池需要关注的参数有哪些?
核心线程数、最大线程池、线程存活时间、时间单位、阻塞队列、拒绝策略、线程工厂
-
线程池执行execute()方法和submit()方法的区别是什么呢?
execute()方法只能接收Runnable类型的参数,而submit()方法可以接收Callable、Runnable两种类型的参数
execute()方法主要用于启动任务的执行,而任务的执行结果和可能的异常调用者并不关心。submit()方法也用于启动任务的执行,但是启动之后会返回Future对象
-
线程池的运行原理?
核心线程数、阻塞队列、最大线程池、拒绝策略
-
如果阻塞队列满了以后,系统重启/宕机,需要考虑什么情况?如何做?
重新发起请求,需要考虑幂等性。
-
synchronized锁的底层原理?
- 加锁方式
- 同步代码块(monitorenter和monitorexit)
- 同步方法(ACC_SYNCHRONIZED)
- 操作流程
- 首先会进入 EntryList 集合,当线程获取到对象的monitor后,进入 Owner区域并把monitor中的owner变量设置为当前线程,同时monitor中的计数器count加1;
- 若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入 WaitSet集合中等待被唤醒;
- 若当前线程执行完毕,也将释放monitor(锁)并复位count的值,以便其他线程进入获取monitor(锁);
- 锁优化
- 加锁方式
-
JVM对synchronized的优化有哪些?
自旋锁、偏向锁、轻量级锁、重量级锁
-
锁消除?
Java虚拟机通过对运行上下文的扫描,经过逃逸分析,去除不可能存在竞争的锁,通过这种方式消除没有必要的锁,可以节省毫无意义的请求锁时间。实质是JIT编译器的同步省略或者叫同步消除
-
锁粗化?
按理来说,同步块的作用范围应该尽可能小,但是加锁解锁也需要消耗资源,如果存在一系列的连续加锁解锁操作,可能会导致不必要的性能损耗。
锁粗化就是将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁,避免频繁的加锁解锁操作。 -
自旋锁与自适应自旋锁?
自适应意味着自旋的时间不再是固定的了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定的
如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而允许自旋等待持续相对更长的时间。另一方面,如果对于某个锁,自旋很少成功获得过锁,那在以后要获取这个锁时将有可能直接省略掉自旋过程,以避免浪费处理器资源
-
锁降级?
一般情况,不会降级
-
synchronized锁和lock锁的区别?
- synchronized是java关键字,jvm层面; lock是类;
- synchronized无法获取到锁的状态, lock可以获取到锁的状态;
- synchronized是自动锁,如果代码执行完毕或发生异常, 他会自动释放锁的资源, lock手动锁,需要人工进行调用unlock方法进行释放锁的资源, 一般都是放在finally; 如果不释放会发生死锁;
- synchronized如果线程a获取到锁的资源,发生阻塞,线程b会一直等待, 而lock如果获取不到锁的资源,线程不用等待就结束了;
- synchronized是可重入、不可中断, 非公平, lock 可重入、 可判断、 可公平(两则皆可);
-
了解ReentrantLock吗?
可重入锁
-
ReadWriteLock是什么?
读写锁、拥有两个条件set
-
ThreadLocal是什么?
线程本地变量
-
ThreadLocal的实现原理
- 每个Thread维护着一个ThreadLocalMap的引用
- ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储
- 调用ThreadLocal的set()方法时,实际上就是往ThreadLocalMap设置值,key是ThreadLocal对象,值是传递进来的对象
- 调用ThreadLocal的get()方法时,实际上就是往ThreadLocalMap获取值,key是ThreadLocal对象
- ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。
-
知道ThreadLocal 内存泄露问题吗?
- key弱引用,value强引用;key可能被销毁
- 建议remove手动清除
-
线程有几种状态?能分别描述一下吗?
创建、准备、运行、阻塞、死亡
-
创建多线程的方式?能具体说一下嘛?
thread、runnable、callable
-
topn
Employee 表包含所有员工信息,每个员工有其对应的工号 Id,姓名 Name,工资 Salary 和部门编号 DepartmentId 。
Id Name Salary DepartmentId 1 Joe 85000 1 2 Henry 80000 2 3 Sam 60000 2 4 Max 90000 1 5 Janet 69000 1 6 Randy 85000 1 7 Will 70000 1 Department 表包含公司所有部门的信息。
Id Name 1 IT 2 Sales 编写一个 SQL 查询,找出每个部门获得前三高工资的所有员工。例如,根据上述给定的表,查询结果应返回:
Department Employee Salary IT Max 90000 IT Randy 85000 IT Joe 85000 IT Will 70000 Sales Henry 80000 Sales Sam 60000 SELECT Department.NAME AS Department, e1.NAME AS Employee, e1.Salary AS Salary FROM Employee AS e1,Department WHERE e1.DepartmentId = Department.Id AND 3 > (SELECT count( DISTINCT e2.Salary ) FROM Employee AS e2 WHERE e1.Salary < e2.Salary AND e1.DepartmentId = e2.DepartmentId ) ORDER BY Department.NAME,Salary DESC;
SELECT b.Name AS Department, a.Name AS Employee, a.Salary from (SELECT *, dense_rank() over(partition by DepartmentId ORDER BY Salary desc) AS Ranking FROM Employee ) AS a INNER JOIN Department b ON a.DepartmentId = b.Id WHERE Ranking <= 3;
-
对 Spring 的一些理解,讲一讲为什么随着 Spring 的发展,它逐渐地违背了当初的设计理念?
- 事务级别
- 数据库默认
- ru rc rr s
- 事务传播行为
- 支持当前事务
- 不存在当前事务、新事务执行
- 不存在当前事务、非事务执行
- 不存在当前事务抛异常
- 不支持当前事务
- 存在挂起当前事务、新事务执行
- 存在挂起当前事务、非事务执行
- 存在当前事务抛异常
- 嵌套
- 支持当前事务
- 事务级别
-
对 Spring IOC 的一些个人理解,来讲一下吧。
Spring IOC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。
-
怎么看待 AOP 的,你觉得它是好事还是坏事?
Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理。常用于计算接口运算时间、记录日志。
-
讲一讲 Java 里的集合类吧。
list map set