1.多线程,线程池
1.如何创建线程
- 实现 Runnable 接口,重写run方法;
- 实现 Callable 接口,重写call方法;
- 继承 Thread 类,重写run方法。
2.基础线程机制
Executors:可以创建四种类型的线程池:
- CachedThreadPool:带缓存的线程池,每来一个任务创建一个线程;
- FixedThreadPool:所有任务只能使用固定大小的线程;
- SingleThreadExecutor:相当于大小为 1 的 FixedThreadPool。
- ScheduledThreadPool:可以执行延迟任务的线程池 。
Daemon:守护线程
sleep:休眠方法
yield:声明了当前线程已经完成了生命周期中最重要的部分,可以切换给其它线程来执行
3.线程中断
- 调用interrupt()方法,抛出 InterruptedException异常
- 调用interrupted()方法,设置线程的中断标记
- 调用 Executor 的 shutdown() 方法
4.线程的状态
新建、可运行、阻塞、无限期等待、限期等待、死亡
5.线程之间的协作
- join()
- wait()、notify()
- await()、signal()
6.同步
- 锁的实现
synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的。 - 性能
新版本 Java 对 synchronized 进行了很多优化,例如自旋锁等,synchronized 与 ReentrantLock 大致相同。 - 等待可中断
当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。
ReentrantLock 可中断,而 synchronized 不行。 - 公平锁
公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非公平的,但是也可以是公平的。 - 锁绑定多个条件
一个 ReentrantLock 可以同时绑定多个 Condition 对象。
2.Redis的内容,Redis的持久化机制,存的set数据太多有什么问题
1.Redis的数据类型
String、List、Set、ZSet、Hash
2.数据结构
跳表,跳表是基于多指针有序链表实现的,可以看成多个有序链表。
与红黑树等平衡树相比,跳跃表具有以下优点:
- 插入速度非常快速,因为不需要进行旋转等操作来维护平衡性;
- 更容易实现;
- 支持无锁操作。
缺点:
- 空间复杂度较高: 跳表需要维护多层索引,因此在存储上需要更多的空间。
- 不适合频繁插入删除: 在频繁插入和删除元素的情况下,维护跳表的索引结构可能会变得复杂,导致性能下降。
3.使用场景
排行榜、缓存、分布式锁
4.内存淘汰策略
- noeviction:当内存使用超过配置的时候会返回错误,不会驱逐任何键
- allkeys-lru:加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键
- volatile-lru:加入键的时候如果过限,首先从设置了过期时间的键集合中驱逐最久没有使用的键
- allkeys-random:加入键的时候如果过限,从所有key随机删除
- volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐
- volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键
- volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
- allkeys-lfu:从所有键中驱逐使用频率最少的键
5.持久化机制
- RDB持久化:将某个时间点的所有数据都存放到硬盘上。可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。如果系统发生故障,将会丢失最后一次创建快照之后的数据。
- AOF持久化:将写命令添加到 AOF 文件的末尾。使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。
always 选项会严重减低服务器的性能;
everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;
no 选项并不能给服务器性能带来多大的提升,而且也会增加系统崩溃时数据丢失的数量。
6.set存数据太多的问题
- 内存消耗: Redis 是内存数据库,存储大量的 Set 数据会占用大量的内存资源。如果数据量超出了可用内存,可能导致 Redis 无法正常工作,甚至系统崩溃。
- 持久化成本: 如果启用了持久化机制(如快照或日志持久化),存储大量的数据会导致持久化操作变得耗时,并可能影响系统的响应性能。
- 数据传输开销: 当数据量较大时,在网络传输数据时可能会引起显著的网络开销,影响数据传输的效率和速度。
- 查询性能: 对大型 Set 进行复杂查询可能会影响查询性能,增加响应时间,特别是在数据集不适合全部加载到内存的情况下。
应对:数据分片、压缩、调整持久化配置、进行性能监控和调优
3.MySQL索引,为什么选择B+树,如果用B树,红黑树,缺点是什么
1.数据结构:B+树
2.为什么选择B+树
- B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具有 B Tree 的平衡性,并且通过顺序访问指针来提高区间查询的性能。
- B+树的数据全部存放在叶子节点,非叶子节点只存放索引,不放数据,所以B+树的高度会更低一点,可以减少磁盘寻道次数。
3.B树的缺点
- 非叶子节点存放数据
- B 树的节点分裂和合并需要频繁地调整树的结构,不支持高度动态的场景
4.红黑树的缺点
- 范围查询性能差
- 当节点数过多时,高度会急速增加,影响性能
4.如何优化SQL查询?优化索引?对于explain语句里面常见的字段含义是什么?
1.优化sql查询
- 选择合适的索引
- 尽量使用limit
- 使用连表查询而不是子查询
- 查询的时候,返回需要的字段而不是全部字段
2.优化索引
- 需要使用多个列作为查询条件时,尽量使用多列索引
- 把选择性更强的列放在前面
- 使用覆盖索引
- 注意索引的失效场景
3.explain语句里常见字段含义
- select_type : 查询类型,有简单查询、联合查询、子查询等
- type: 表示访问类型,用于表示查询的访问方式,如ALL(全表扫描)、index(使用索引扫描)、range(范围查询)等。
- key : 使用的索引
- rows : 扫描的行数
5.MySQL事务,ACID,隔离级别
1.Mysql事务:
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
2.ACID:
- 原子性(Atomicity)
事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。回滚可以用回滚日志(Undo Log)来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。 - 一致性(Consistency)
数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。 - 隔离性(Isolation)
一个事务所做的修改在最终提交以前,对其它事务是不可见的。 - 持久性(Durability)
一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。
3.隔离级别
- 未提交读(READ UNCOMMITTED)
事务中的修改,即使没有提交,对其它事务也是可见的。 - 提交读(READ COMMITTED)
一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。 - 可重复读(REPEATABLE READ)
保证在同一个事务中多次读取同一数据的结果是一样的。 - 可串行化(SERIALIZABLE)
强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。