JAVA基础八股文
问:java的流有哪些呢?
从方向方面,主要就是输入流和输出流。
从单位方面,主要就是分为字节流和字符流。字节流主要就是InputStream,OutputStream。字符流主要就是Reader,Writer。
问:抽象类和接口有什么区别呢?
从方法编写方面,抽象类中可以抽象方法和普通方法,而接口中只能编写抽象方法。
从继承和实现方面,抽象方法只能继承一个类并且可以实现多个接口,而接口可以继承多个接口。
在变量的定义方面,接口只能定义静态变量,抽象类可以定义普通变量和静态变量。
问:final关键值有了解过吗?
在修饰方法的时候,说明该方法无法被重写。
在修饰类的时候,说明该类无法被继承。
在修饰属性的时候,说明该变量从创建到销毁过程中不会改变。
在修饰形参的时候,说明该形参的引用在方法执行前后都会不发生改变。
问:异常类有哪些?
异常主要就是Exception,Error。
Exception主要就是运行时异常和检查时异常,为了保证代码恶的正常运行,我们需要主动使用try/catch进行捕获,常见的就是IoEception,SQLExceptinon。
Error主要就是就是发生在运行时的异常,就比如:oom,threadDeath。
Filter和Interceptor有说明区别?哪个先执行呢?
- 在作用域方面,Filter作用域每个请求,而interceptor主要就是对Controller方法的请求起作用。
- 在执行时机方面,filter会在请求加入dispatchServlet前和返回给客户端前执行,而interceptor会在执行Controller方法的时候和进行视图渲染前执行。
- Filter会像执行而interceptor随后执行。
篇幅限制下面就只能给大家展示小册部分内容了。包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记的【点击此处即可】即可免费获取
Redis八股文
问:Redis数据结构的底层实现由了解过吗?
String类型的底层使用动态字符串实现的。
List类型的底层使用双向链表+压缩数组实现的。
set类型的底层使用哈希表+数组整数数组实现的。
hash类型的底层使用压缩数组+哈希表实现的。
zset类型的底层使用压缩数组+跳表实现的。
问:zset的底层结构有了解过吗?
zset的底层结构主要就是跳表+压缩列表。
压缩列表:本质就是一个数组,在其中记录 列表的长度,尾部得偏移量,列表的个数。
跳表:就是基于二分查找的思想,对链表创建多级索引,就是基于每隔一个节点做索引,以此类推,创建索引的层数就是 logn + 1。整个查找过程就是在多级索引间跳来跳去。
问:我看你在做项目的时候都使用到redis,你在最近的项目中哪些场景下使用redis呢?
缓存和分布式锁都有使用到。
问:说说在缓存方面使用
1.在我最写的物流项目中就使用redis作为缓存,当然在业务中还是比较复杂的。
2.在物流信息查询模块使用中使用二级缓存,一级缓存使用的是Caffeine,二级缓存就是使用redis。
问:对缓存击穿,缓存雪崩,缓存穿透有了解过吗?说说者三个缓存问题的解决方案吧。
1.缓存击穿:某个热点key设置了过期时间,在高并发查询的情况下,该热点key过期了,导致大量的请求去访问数据库,最终压垮数据库。
解决方案:
(1)不给热点key设置过期时间(在redis中设置的过期时间都是逻辑过期时间,通过逻辑字段来判断key是否过期)。
(2)使用分布式锁,保证每次只有一个请求去访问数据库,在每次访问数据库前再做一次查询缓存的操作,然后获取锁并去数据库查询,将查到的数据重新缓存起来,下一次请求就会在缓存中查询到数据,就不会查询数据库,防止压垮数据库。
2.缓存雪崩:第一种情况:大量的key设置了相同的过期时间,在同一大量的key失效,导致大量的请求去访问数据库,导致压垮数据库。第二种情况:redis宕机。
解决方案:
(1) 错开key的过期时间(TTL):在每个key的统一过期时间上在随机加上1~5分钟的过期时间。
(2)设置服务降级,服务熔断,服务限流,到达阈值的时候直接返回自定义的错误信息。(作为系统的兜底策略)
(3)为redis搭建集群,就包括哨兵模式,集群模式。
(4)做二级缓存。(可以重点介绍,就引导面试官到运单信息查询模块,给他介绍二级缓存的实现还有缓存同步的问题,主要讲caffeine缓存同步的问题)
3.缓存穿透:查询的key在缓存和数据库中都不存在,每次都会进入数据库查询,当大量的这种key访问数据库,就会导致缓存穿透。(这种情况多半上是恶意攻击)
解决方案:
(1)在缓存中储存空值:当在数据库中没有查到数据时,将key关联null的键值对存储到缓存中,后续就会走缓存,这种解决方案缺点很明显,就是存储大量无用的存储,浪费空间。
(2)使用布隆过滤器:在查询缓存的时候先去布隆过滤器中查询是否存在缓存,再去查询缓存。
问:具体讲讲你对这个布隆过滤器理解?
布隆过滤器类似hash表叫做bitmap(位图),在没有位置存放的是二进制的数据,1表示存在,0表示不存在。通过哈希函数计算储存位置。在后续查询缓存前先去布隆过滤器中查询数据是否存在,如果存在才去查缓存,如果不存在就直接返回空。
布隆过滤器的优点就是:储存二进制的数据,而非真实的数据,查询速度快。缺点:判断数据是否存在有误判率,不能做删除操作。
为了降低布隆过滤器的误判率,因为两个数据的hashCode可能相同,所以我们可以设置多哈希函数操作,较低过滤器的误判率。
我们主要是根据redisson设置布隆过滤器,可以设置其误判率。在高并发的场景下,一般误判率控制在5%之内就可以了。
问:说说分布式锁方面的使用
在项目的支付模块中的扫码支付为了保证交易单的状态不会被除当前业务的其他业务修改,计算运力,我们都会使用分布式锁。
&nbs