Java基础
- 什么是集合类
- 集合是用于存放Java对象的一种容器,也是Java中的一种数据结构
- 集合类中存放的是对象的引用,而不能存放基本的数据类型
- 集合类中提供算法和数据结构,使得程序运行效率提高
- 集合类提供数据处理的API,提高了开发的效率
- 有哪些常见的集合类
- 集合类由Collection和Map两个接口组成,Collection又包含了List和Set两个接口
- List接口的实现类有:ArrayList,LinkedList,Stack,Vector等
- Set接口的实现类有:HashSet,TreeSet,LinkedHashSet等
- Map接口的实现了有:HashMap,TreeMap,HashTable,ConcurrentHashMap,Properties等
- 数组和集合的区别是什么
- 数组是定长的,集合的长度可变
- 数组中存放的基本数据类型,集合中存放的引用数据类型
- 数组中只能 存放一种数据类型,集合中可以存放多种数据类型
- 集合类中是否可以存储NULL值
- List接口中:ArrayList,LinkedList,Vector中均可存储多个NULL
- Set接口中:HashSet和LinkedHashSet中可以存放一个NULL,TreeSet中不能存在NULL
- Map接口中:HashMap的key和value可以为NULL,TreeMap中的key不可以为NULL,value可以为NULL,HashTable和ConcurrentHashMap的key和value均不可以为NULL
- ArrayList和LinkedList之间的区别
- 底层实现:ArrayList使用动态数组实现,LinkedList使用双向链表实现
- 性能:ArrayList可以通过下标堆数据随机访问,因此访问数据的效率高,但是增删的操作效率比LinkedList低,因为每一次增删操作都需要调整后面数据的位置,或者进行扩容操作
- 空间开销:ArrayList的空间开销主要是数组中预留的空间位置,LinkedList主要的空间开销是节点对相邻节点位置记录的引用空间
- ArrayList和Vector之间的区别
- Vector是线程安全的,实现的方法中都是用Synchronized修饰符实现线程安全,ArrayList不是线程安全的,在不需要考虑线程安全性的情况下使用ArrayList效率更高
- Vector和ArrayList都有一个默认数组的初始大小,在必要的时候对数组进行扩容,Vector会将数据扩充到原来的2倍,ArrayList会扩充到原来的1.5倍
Redis
- Redis为什么那么快
- Redis是基于内存的,减少了IO操作,提高了性能
- Redis的事务处理器是单线程实现,减少了线程上下文切换以及线程并发的锁定问题
- Redis使用IO多路复用机制
- Redis的事务处理器为什么是单线程
- Redis中可以操作一些复杂的数据结构,比如List,Hash,对于这些复杂的数据结构会产生一些细粒度的操作,如果使用多线程会引入许多的细粒度锁问题,从而影响性能
- 单线程的性能也非常强大,效率也很高,虽然单机多线程的性能上限更大,但是在开发环境中,单机多线程也无法满足很多性能需求了,可以使用单线程集群方案来进行实现和代替
- 缓存的三大问题以及解决方案
- 缓存穿透:大量的对一个不存在的key进行请求
- 将不存在的key在缓存中赋以空值,防止请求直接到数据库
- key值校验,使用布隆过滤器等
- 缓存击穿:一个key过期时,伴随着大量的请求
- 使用互斥锁,允许一个请求到达数据库,将数据读取到缓存中后,其他的请求就可以访问缓存中的数据
- 熔断降级,返回空值或者错误信息
- 热点数据不过期策略
- 缓存雪崩:大量的key同时过期
- 热点数据不过期策略
- 随机散列每一个数据的过期时间,防止同时过期
- 缓存穿透:大量的对一个不存在的key进行请求
- 布隆过滤器的实现原理
- 将需要插入的key值通过多个哈希函数获取对应的哈希值,在一个很长的二进制向量中,将这些哈希值散列得出的位置标记为1,需要判断一个key值是否有效时,可以查看key散列的这些位置上是否都为1,如果存在一个值为0,那么这个key肯定不是有效的,如果都为1,那么这个key值很有可能是有效的
- 缓存的持久化策略
- 先持久化再更新缓存:更新缓存之前,可能会有并发的请求获取到缓存中的脏数据
- 先更新缓存再持久化:如果先删除了缓存,可能会出现不命中然后读取数据库中的脏数据
- 解决方式:使用2PC协议,使用缓存过期策略,使用canal监听实现binlog实现异步更新
- 如何实现Redis的高并发
- Redis通过集群架构,使用主从读写分离,使用主节点进行写,并将数据同步给其他的节点,从节点进行度,实现高并发
- 如何保证Redis的原子性
- Redis的事务处理器是单线程的,因此每一个操作都是原子的,但存在一些先set后get的操作,可能导致数据不一致
- 可以使用inc,dec,setnx命令来实现原子操作
- 可以给客户端加锁
- 可以使用Lua脚本实现CAS操作
- Redis有哪些应用场景
- String可以用于分布式锁、分布式会话,计数器等
- Hash可以用于用户对象信息,用户访问量
- List可以用于简单队列,关注列表时间轴
- Set可以用于赞、踩、标签
- ZSet可以用于排行榜,好友关系链表等
Linux
- 如何理解Linux系统中一切皆文件
- Linux系统中的所有软硬件都通过文件的形式进行管理和维护,这样的好处是开发人员仅需要一套API和开发工具就可以调用Linux系统中的绝大部分资源,但缺点就是每一个硬件都需要和根目录下的某一个目录进行挂载,否则就无法使用
- 说一说Linux中文件的权限配置
- 可以使用chmod(change mode)指令来配置文件的权限
- 文件可读使用4,可写使用2,可执行使用1
- 可读可写可执行4+2+1 = 7
- 可读可写 4+2 = 6
- 可读可执行 4+1 = 5
- 使用三个数字分别代表拥有者的权限,同组成员的权限和其他用户的权限
- Linux中的常用命令
- ls/mkdir/rm/cp/tar/gzip
- ps/netstat/find/kill/grep/tcpdump
- top/free
- mount/chmod/su
- 系统平均负载是什么
- 系统平均负载就是在一定时间内系统中的可运行进程的数量
- 可运行进程是指,没有等待IO,没有自动进入等待状态(调用wait),没有停止
- 一般来说如果系统平均负载为3表示系统运行顺畅,超过5就表示存在问题