java面试题
ThreadLocal
概念:线程本地变量,
历史:一般对象非线程安全,在多线程环境下,必须加锁。但spring的DAO未采用线程同步机制
因为同步限制了并发,性能损失。
threadLocal为每个线程维护变量的副本,实现思路,使用Map存储key threadLocal对象(弱引用)、value线程的变量副本 (需要remove)
区别:线程同步是以时间换空间,threadLoal是以空间换时间
实用:spring中大多数bean是单例。事务管理的连接池connection
2、BeanFactory与ApplicationContext
相同点:都可以实例化bean,都是interface
不同点:BeanFactory是getBean时实例化,ApplicationContext是启动容器时实例化单例的bean
BeanFactory不支持国际化
Web容器使用的Web ApplicationContext,并且增加了getServletContext
3、HashMap和HashTable区别
都实现了Map接口
HashTable线程同步(线程安全使用了sync)、HashMap非线程同步
HashTabel不允许空值,HashMap允许value多空
HashTabel默认大小11,增加方式old*2+1,hashTable默认16,增长方式*2
HashTabel父类Dictionary,HashMap继承AbstractMap。
4、HashMap哪些线程安全的方式
ConcurrentHashMap,拆分多个块,性能好,CAS(compare and swap)
Collections.syncronizedMap返回一个新map ,锁住方法,性能差
5、HashMap扩容有哪些优化/为什么用2倍
1.8后2倍,判断尾数1,还是0进行判断时老索引还是新索引
6、MVCC多版本并发控制
数据库3种并发场景,
读读、无问题
读写、线程安全问题、脏读幻读不可重复读
写写、更新丢失
MVCC解决读写的无锁并发控制,给数据事务增加版本信息。避免加锁阻塞性能问题
解决了读写时的问题,脏读,幻读,不可重复读。不能解决更新丢失。
实现原理:
依赖于记录中的3个隐藏字段(最后一次id、上一次版本、主键)
undulog
read view
7、插件实现原理
动态代理(invocation),类似AOP切面的方式
8、Mybatis优缺点
优点:比JDBC减少代码量,不需要手动开关连接,兼容数据库
插件多(分页PageHelper/逆向工程-反向生成代码)、
支持动态sql
支持对象与ORM关系映射
缺点:sql语句编写工作量大(字段多关联多,要写到xml里),依赖数据库,
9、MyBatis和Hibernate区别
Hibernate配置复杂, 使用简单。自动生成sql,优化难
10、Mybatis ${} #{}
#{} 预编译处理(替换为?执行时再给值),防止sql注入,提高安全性
${} 字符串替换
11、数据库的隔离级别
读未提交-脏读
读已提交-不可重复读
可重复读-幻读 (默认级别)可使用MVCC解决。一般使用默认
串行化
12、mysql主从复制原理
BinaryLog、Relaylog
Master 改数据后,写入binLog
slave通过IO thread读取binLog,写入RelayLog
salve使用Sql thread读取Relaylog 执行sql
解决的问题:主库写,从库读。保持业务正常运行。多库存储提高单个IO性能
13、mysql聚簇和非聚簇
索引是存在硬盘。索引类型跟引擎相关
判断标准:数据和索引是否在一起。
Innodb索引跟数据存在一起。其他多索引放聚簇索引的key。即既有聚簇索引,也有非聚簇
myisam只有非聚簇
14、索引的基本原理
以块为单位,
innodb:b+树
Memory:hash索引 速度快,不能查区间
B+树优点:
非叶子节点不包含表数据,树的高度小,这样单次请求IO少
查询路径长度相同,效率稳定
遍历时从符合条件的某个叶子节点开始遍历,效率高
支持区间查询
缺点:随机IO
15、mysql的锁有哪些类型
共享锁(共读)、排他锁
行锁(包括记录锁、间隙锁、临键锁)、页锁、表锁、、
16、mysql的执行计划
使用explain语句查看,包括
Id 表示操作顺序
table 哪个表
Type表示访问方式、一般达到range,出现all、index注意
Key使用的哪个索引(mysql自动优化选择)。可以使用强制索引,对比效率选择
Row哪个列
Extra 其他一些详细信息,using where进行了全表扫描,using index使用索引覆盖情况
17、spring和springMVC
springMVC属于spring,针对Web开发的路径映射和视图渲染
springBoot专注于开发微服务接口
18、springboot自动配置原理
启动类注解@springBootApplication
是一个组合注解包括@SpringBootConfiguration\@EnableAutoConfiguration
自动装配主要依赖@EnableAutoConfiguration,import了AutoConfigurationImportSelector类
关键的是selectImports方法,会获取@EnableAutoConfiguration注解的,会扫描META/spring.factories获得自动装配类
还有其他去除重复或者不需要的进行移除。
19、spring MVC工作流程
用户请求->前端控制器dispatchServlet拦截—>给HandlerMapping返回Handler-->
处理器适配器HandlerAdapter—>执行handler返回ModelAndView—>前端控制器拿到后给视图解析器处理返回View—>渲染视图响应用户
这里面包含了springMVC的九大组件、其他包括异常处理HandlerExceptionResolver,主题解析ThemeResolver、处理上传请求
20、spring的核心
是一个IOC AOP容器框架
21、spring的事务传播机制(建立在数据库事务基础上,就是控制mysql事务Spring的事务隔离级别==数据库的隔离级别)
多个事务方法相互调用时,控制事务在这些方法直接的传递方式
Required 默认的。没有事务则新建事务,存在事务则加入事务
Support 有事务则加入,没事务以非事务执行
Mandatory 有事务则加入,没事务抛异常
required_new 创建新事务,有事务则挂起改事务,
Naver 不用事务,有事务则异常
Nested 有事务则嵌套执行 和其他区别是在于异常时是否进行回滚
22、srping事务的实现原理
使用:
编程式事务(自己写)
声明式事务 (@Transcation)使用AOP思想,动态代理 生成代理对象,
Spring事务无法解决跨服务间调用,所以需要分布式事务。
分布式事务的实现方案
2pc、3pc。3比2多了询问阶段,然后是准备和提交
tcc
消息中间件的最终一致性
分布式框架seata
23、静态代理、动态代理
动态代理是在运行时,由反射机制动态产生的,两种方式jdk和cglib
Jkd为接口,生成的代理实现了接口,
Cglib为类,实现子类重新了父类的方法
@Transaction需要定义public,不然jdk和cglib无法访问到,此时spring事务就失效了,
其他失效情况:
数据库不支持、
Bean没有被容器管理、(需要@Service)
本类调用本方法,无法进行aop、
抛出的异常不识别(注解里面标注出异常类)
多线程导致数据库连接非同一个
21、spring的单例bean是否线程安全
Bean默认时单例,没有进行多线程封装。如果存储数据,则不是安全的。没有存储数据,则安全。
需要解决可以用ThreadLocal把变量变成线程私有,或者要线程间共享只有加锁
Spring的bean除了默认单例,还有其他作用域,
protoType(每次创建新的)、
session(不同session不同实例)
22、spring框架哪些设计模式和应用
工厂、模版 BeanFactory
代理,AOP
策略,加载资源根据不同文件使用不同的方法,ClassPath Resource
单例,bean
观察者,ApplicationEvent,publisher,listener
适配器,Adapter
装饰者,wrapper,Decorator
23、mysql索引类型
普通索引、允许被索引的数据列重复
唯一索引、数据唯一
主键索引
联合索引
全文索引(倒排索引)
24、bean的声明周期
通过反射进行bean对象的创建、申请空间、配置默认属性
设置属性
检查Aware接口并设置相关依赖,即使用Aware接口的子类方法进行配置
BeanPost Processor进行前置处理
检查是否设置了InitialzingBean接口
是否有自定义init-method方法
BeanPost Processor后置处理
注册Destruction注销回调接口
25、如何处理Mysql的慢查询
1、开启慢查询日志,定位问题sql语句
26、bean自动装配,有哪些方式
Bean的属性值在进行注入的时候通过某种特定规则去容器查找,并设置到对象属性中
配置文件中:
有no,默认情况,通过ref属性手动设定
byName
byType
constructor
autodect 先找constructor,在找byType
注解使用@AutoWired
27、事务四大特征ACID
原子性、要么都成功要么都失败
一致性、底层数据的完整性,例如a-了,b+了,但是总量不变
隔离性、多个事务相互独立
持久性、所有的改动在结束前都要保存,防止丢失
28、对AOP的理解
面相切面编程、使用代理实现,目的是为了解耦,把核心业务和非核心业务分离,比如日志打印、全局异常拦截、声明式事务
声明式事务思路,在bean初始化时判断@transactional注解,有的化返回代理类,invoke带有transactionInterceptor的拦截器
执行拦截链,拦截器中执行提交事务回滚事务等方法
29、对IOC的理解
控制反转,原来是需要我们自己去new对象和设置属性,现在交给容器控制,而且内部依赖的对象也会生成。
30、索引的设计原则
思想就是要保证索引字段越小越好,B+树的叶子可以存储更多数据、
1、where,join适合出现索引
2、基数小的没必要,比如只有3种状态
3、并不是越多越好、占用IO过大
4、外键要创建索引
6、频繁更新的不要用索引
7、大对象不要创建索引,会导致B+树变高
30、ArrayList和LinkList区别
ArrayList基于索引Index的,查找快
LinkList基于链表的,插入删除快
31、高并发中的集合有哪些
32、分布式ID方案
UUID,复杂度低,占空间,随机
数据库主键,只适合单机
Redis自增,是单线程的所以可以生成全局唯一ID
雪花算法
雪花算法ID有哪些部分组成
符号位,时间戳、机器id,序列号
33、分布式锁
在分布式系统中进行加锁,
有Redis分布式锁,基于redis扩展的redisson,原理:setnx(set if not exists) key 及 设置UUID判断是否自己的锁,watchdog监听过期。
基于zookeeper,临时节点、顺序节点
基于数据库的主键或唯一索引的唯一性(mysql是如何做分布式锁),分布式是增加一个id
Redis中如果 加锁没释放(代码没有,或者程序挂了),就会出现死锁。解决是加过期时间
两者的区别:zookeeper每次锁需要创建节点、释放节点,高并发是效率慢,
34、计算器算法是什么
在一定时间周期内,累计够次数后,清零重新累计。
原理是使用redis自增值,
存在问题:在另外计算的一个时间周期会超过
35、滑动时间窗口算法
目的解决计算器算法的问题,实际周期切分多个小的时间窗口,分别计算,然后根据时间滑动,并删除过期的小窗口
36、漏桶限流算法
37、令牌桶算法
38、微服务的设计原则
单一职责
服务自治、独立开发测试构建部署
轻量级通信、利用restfu,或者mq
粒度进化、跟随业务发展更新粒度
39、BigDecimal
原因:小数点的二进制生成过程,会导致小数点的精度会丢失
原理:把小数扩大n倍,然后在整数维度上进行计算,int scale保留精度信息 BigInteger存储整数信息,而BigInteger是使用数组存储
解决大数溢出
40、CAP
分布式系统特性
C 一致性 A可用性 P分区容错性
由于C和A无法兼得,牺牲强一致性,提出了BASE理论,BA基本可用,S软状态,E 最终一致性。
实现CAP和BASE理论、分布式事务方案
2pc、3pc
41、2pc 3pc tcc
(数据库)事务 要么都成功要么都失败,ACID 本地事务—>分布式系统中的分布式事务—>如何保证ACID —>2pc、3pc
3pc比2pc增加了Can Commit阶段,增加了超时机制。但是都解决不了数据一致性。
Tcc 应用层面的2pc,自定义粒度
使用mq实现最终一致性
41、RabbitMq如何确保消息发送和消息接受
发送方一个回调接口ConfirmCallback,确认到了exchange
接收方一个回调接口ReturnCallback,
接受确认Ack
42、Kafka
采用了pull模式
43、分库分表
思路
垂直分库:从业务角度拆库,例如订单和用户信息
垂直分表:把热点数据和非热点数据分开,提高查询速度
水平分表:业务过大时,按照一定规则拆表
方案:
Hash取模
Range范围
解决方案:Mysql的分库分表
中间件:Proxy模式,Client模式
44、redis持久化机制
Redis数据都存在内存中,数据需要通过持久化机制防止宕机而丢失
RDB(RedisDataBase)和AOF(Append onlyFIle)
RDB通过快照形式,fork出子进程,防止阻塞。使用COW提高复制速率
AOF存储指令序列,追加文件过大会重写优化
45、Redis线程模型有哪些,单线程为什么快
单线程Reactor模型,IO模型使用了多路复用器,linux使用了EPOLL,内部会有其他线程执行任务
单线程不需要锁的复杂度,减少了上下文切换
46、Redis的过期键有哪些删除策略
使用绝对过期时间,保证时间一直流逝
淘汰过期key有主动和被动方式,
访问的时候key被发现并主动过期
每秒10次查找删除,定期删除,随机检测
47、Redis缓存如何回收
回收是针对内存不足的时候,放弃占用内存
LRU、LFU
48、Redis集群方案
主从、分片
主从复制手动切换
主从复制哨兵控制
分片-路由索引、中间件、自身cluster
49、redis事务是如何实现的
通过几个关键字实现。Multi、exec、discard、watch,执行这些命令
50、redis主从复制原理
保持连接时,发送命令,断开链接重新链接后,尝试重同步,无法部分重同步,进行全量同步
非阻塞的
51、zookeeper watch机制
52、什么样的数据放在redis里
1、String Hash 热点数据,session共享,分布式锁
2、Int 全局ID,计数器,限流
3、List 存储有序的,消息列表,活动列表,博客文章列表
4、Set 无序 抽奖 点赞,签到,商品标签,共同好友 筛选取交集
5、Zset 有序元素 排行榜
https://zhuanlan.zhihu.com/p/383898640
53、redis相对于其他hashMap具有更丰富的数据类型,跨语言,功能丰富-持久化机制,支持集群分布式
https://www.zhihu.com/people/Java_3y