针对重点:
Spring 源码
Java多线程 JUC容器
JVM
redis 原理
MySQL 常见问题
分布式架构常用的框架
String、StringBuffer、StringBuilder最大的不同是String不可变,后者可变。StringBuffer是线程安全的,StringBuilder线程不安全速度较快。对于拼接字符串:StringBuilder > StringBuffer > String
带着问题与技术关键词,有目标的开启体系化学习之旅~
- 基础:
- 强引用、弱引用、虚引用、软引用
- final关键字的作用 (方法、变量、类)
- 泛型、泛型继承、泛型擦除
- jdk ServiceLoader
- LinkedList、LinkedHashMap、LRU
- 装饰者模式、代理模式、责任链模式、工厂模式、适配器模式、建造者模式、单例模式、模板模式、观察者模式…
- 关于精度损失问题:int、long 超过最大值
- 关于注解:元注解的种类、继承java.lang.Annotation、注解的基础类型、注解的常用方法
- 关于ClassLoader,类加载器,双亲委派模型
- J.U.C
- 线程池参数说明,线程池的线程回收、shutdown
- 线程池的生命周期?
- 线程池的核心模型Worker对象的运作流程是怎样的?
- 线程池的拒绝策略有哪4种?
- 线程池的提交,execute与submit有什么区别?在实际开发中需要注意哪些问题?
- threadlocal原理,数据结构
- 并发集合类了解哪些?
- ConcurrentHashMap
- CopyOnWrite集合、原理、锁机制
- ConcurrentLinkedQueue、LinkedTransferQueue、ArrayBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue
- AQS 原理:
- 独占 & 共享
- state & CHL队列
- 锁:
- Synchronized、ReentrantLock、RWLock、Condition、LockSupport、StampedLock、
- 概念:CAS 自旋、重入、偏向
- volatile:
- 多线程共享 & 阻止指令重排序
- jvm的逃逸分析 & Tlab & 消除伪共享 & UNsafe &
- atomic:
- CAS的缺点,自旋、ABA问题
- atomic 原子性、Reference、referenceArray、longadder
- 并发控制:
- barrier、countdownlatch、exchanger、future、semaphore
- jvm虚拟机:
- 虚拟机内存模型
- 新生代(Eden S0 S1)、老年代 、MetaSpace (比例)
- 垃圾回收算法(引用计数、标记压缩、清除、复制算法、分区)、垃圾收集器
- GC停顿、吞吐量,进入老年代阈值、大对象回收问题等
- jvm性能调优、参数配置
- 常用命令:jstat、jmap、jstack等
- 内存溢出分析:堆内、堆外 (含义、如何设置)
- CPU飙升:死锁、线程阻塞
- 关于GC: minor major full
- stw,安全点等
- 数据结构&算法
- 数组、链表、树、队列…
- 关于时间复杂度,时间换空间转换案例
- 关于排序、冒泡、快排、递归、二分搜索、位运算
- Spring
- Spring生命周期,流程梳理
- Spring扩展点作用
- Spring IOC AOP 基本原理
- 动态代理
- BeanPostProcessor 作用?
- ApplicationContextAware 的作用和使用?
- BeanNameAware与BeanFactoryAware的先后顺序?
- InitializingBean 和 BeanPostProcessor 的after方法先后顺序?
- ApplicationListener监控的Application事件有哪些?
- Spring模块装配的概念,比如@EnableScheduling @EnableRetry @EnableAsync,@Import注解的作用?
- ImportBeanDefinitionRegistrar 扩展点用于做什么事情?
- ClassPathBeanDefinitionScanner 的作用?
- NamespaceHandlerSupport 命名空间扩展点的作用?
- 如何实现动态注入一个Bean?
- 如何把自定义注解所在的Class 初始化注入到Spring容器?
- BeanDefinition指的是什么,与BeanDefinitionHolder的区别,Spring如何存储BeanDefinition实例?
- ASM 与 CGlib
- Spring的条件装配,自动装配
- RPC通信框架
- Dubbo
- Dubbo的Spi机制?
- Dubbo的核心模型 invoker、invocation、filter
- Dubbo的隐式传递?
- Dubbo的泛化调用?
- Dubbo的export与importer时机?
- Dubbo的服务调用过程?
- Dubbo的负载均衡策略?
- Dubbo的集群容错?
- Dubbo
- 网络通信
- IO / NIO
- IO NIO区别?
- 多路复用的概念,Selector
- Channel的概念、Bytebuf的概念,flip、position…
- FileChannel 如何使用?
- RAF使用,seek、skip方法
- Netty
- 关于Netty的Reactor实现?
- Netty的ByteBuf有哪些?
- 内存与非内存Bytebuffer的区别与使用场景?
- 池化与非池化buffer的区别与使用场景?
- 关于Netty的请求Buffer和响应Buffer?
- Netty的ChannelPipeline设计模式?
- Netty的核心option参数配置?
- Netty的ChannelInboundHandlerAdapter和SimpleChannelInboundHandler关系?
- Netty的EventLoop核心实现?
- Netty的连接管理事件接口有哪些常用方法(ChannelDuplexHandler)?
- Netty的编解码与序列化手段
- Netty的FastThreadLocal实现?
- Netty中应用的装饰者 和 观察者模式在哪里体现?
- IO / NIO
- MQ
- API使用,常用生产消费模型,集群架构搭建
- 常见问题,消息可靠性投递、幂等性保障
- 概念、原理、存储、消息投递、通信机制、性能相关优化
- MQ常见的作用于目的、服务解耦、削峰填谷等
- RocketMQ
- Kafka
- RabbitMQ
- ActiveMQ
- 缓存
- 内存缓存
- 堆外内存缓存 回收释放
- Redis
- 缓存穿透、雪崩、热点Key、大Key、无底洞问题,缓存更新与淘汰、缓存与数据库的一致性
- Redis的幂等性
- Redis的分布式锁实现
- Redis的原子性,Redis的特点
- Redis集群相关问题、一致性hash、slot概念等
- 内存缓存
- 流控组件
- Hystrix
- Sentinel
- 高可用服务中间件
- Zookeeper / Curator
- Nginx
- Haproxy
- LVS
- Haproxy
- 数据库存储&调度
- Sharding-JDBC
- ElasticJob
- 调度平台相关:DAG、airflow等
- 搜索相关度
- ELK ,数据库加速、主搜(算法)
- Logback、Slf4j2
- Solr & Lucene
1.请详细说明HashMap和HashTable以及CocurrentHashMap的异同。
2.什么是网络IO模型?什么是多路复用IO?select和epoll的差别是什么?
3.请详述TCP三次握手的全过程,并且如果没有第三次握手会有什么问题?
4.常用的线程池有哪些?它们各自的应用场景有哪些?
5.请详述Java类加载机制,以及双亲委派模型的好处。
6.你对Java并发包组件了解多少?
7.什么时候多线程会发生死锁?你将如何来预防死锁?
8.请详述操作系统的用户态和核心态切换条件以及说明白为什么要切换
9.数据库事务有哪些特点?事务隔离级别?项目中的事务怎么实现?脏读、不可重复读、幻读能各举个例子吗?
1.什么是数据库索引?B+树?为什么要建索引?什么样的字段需要建索引,建索引的时候一般考虑什么?索引会不会使插入、删除作效率变低,怎么解决(分表)?
2.设计模式,单例模式,怎么保证线程安全?锁效率太低,怎么提高效率?
3.什么是CAS?CAS的本质是什么?什么是原子性?Compare and Swap两步,为什么能保证原子性(涉及到CPU指令)?
4.分布式锁的实现你都知道哪些?你更推荐哪一种锁?
5.Redis的持久化操作有哪些?
6.如何利用Redis处理热点数据?
1.你有接触过哪些消息队列中间件?你将如何来选型?
2.谈谈你的SOA以及微服务的理解
3.能具体谈谈Spring Cloud服务和注册流程吗?
4.分布式的CAP有了解么,分别指什么?
5.谈谈网络编程NIO和Netty相关的内容,以及Netty的线程模型,零拷贝是如何实现的?
1.Redis是单线程还是多线程?Redis的分布式集群怎么做?
2.了解过集群雪崩么?
3.谈谈高并发场景下削峰,限流的实现?
4.你之前工作的项目里个人最满意的部分,谈谈你的架构设计思路?
Mybatis 面试题
1. MyBatis 中 #{}和 ${}的区别是什么?
{}是预编译处理,${}是字符替换。
在使用 #{}时,MyBatis 会将 SQL 中的 #{}替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样可以有效的防止 SQL 注入,保证程序的运行安全。
2. MyBatis 有几种分页方式?
分页方式:逻辑分页和物理分页。
逻辑分页: 使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索。
物理分页: 自己手写 SQL 分页或使用分页插件 PageHelper,去数据库查询指定条数的分页数据的形式。
3. RowBounds 是一次性查询全部结果吗?为什么?
RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在你执行 next()的时候,去查询更多的数据。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。
4. MyBatis 逻辑分页和物理分页的区别是什么?
逻辑分页是一次性查询很多数据,然后再在结果中检索分页的数据。这样做弊端是需要消耗大量的内存、有内存溢出的风险、对数据库压力较大。
物理分页是从数据库查询指定条数的数据,弥补了一次性全部查出的所有数据的种种缺点,比如需要大量的内存,对数据库查询压力较大等问题。
5. MyBatis 是否支持延迟加载?延迟加载的原理是什么?
MyBatis 支持延迟加载,设置 lazyLoadingEnabled=true 即可。
延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息。比如调用 a. getB(). getName(),这个时候发现 a. getB() 的值为 null,此时会单独触发事先保存好的关联 B 对象的 SQL,先查询出来 B,然后再调用 a. setB(b),而这时候再调用 a. getB(). getName() 就有值了,这就是延迟加载的基本原理。
6. 说一下 MyBatis 的一级缓存和二级缓存?
一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致的,有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据。当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认一级缓存是开启的。
二级缓存:也是基于 PerpetualCache 的 HashMap 本地缓存,不同在于其存储作用域为 Mapper 级别的,如果多个SQLSession之间需要共享缓存,则需要使用到二级缓存,并且二级缓存可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态)。
开启二级缓存数据查询流程:二级缓存 -> 一级缓存 -> 数据库。
缓存更新机制:当某一个作用域(一级缓存 Session/二级缓存 Mapper)进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
7. MyBatis 和 hibernate 的区别有哪些?
灵活性:MyBatis 更加灵活,自己可以写 SQL 语句,使用起来比较方便。
可移植性:MyBatis 有很多自己写的 SQL,因为每个数据库的 SQL 可以不相同,所以可移植性比较差。
学习和使用门槛:MyBatis 入门比较简单,使用门槛也更低。
二级缓存:hibernate 拥有更好的二级缓存,它的二级缓存可以自行更换为第三方的二级缓存。
8. Mybatis 插件原理
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。