面试问题记录

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.同步

  1. 锁的实现
    synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的。
  2. 性能
    新版本 Java 对 synchronized 进行了很多优化,例如自旋锁等,synchronized 与 ReentrantLock 大致相同。
  3. 等待可中断
    当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。
    ReentrantLock 可中断,而 synchronized 不行。
  4. 公平锁
    公平锁是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。synchronized 中的锁是非公平的,ReentrantLock 默认情况下也是非公平的,但是也可以是公平的。
  5. 锁绑定多个条件
    一个 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存数据太多的问题

  1. 内存消耗: Redis 是内存数据库,存储大量的 Set 数据会占用大量的内存资源。如果数据量超出了可用内存,可能导致 Redis 无法正常工作,甚至系统崩溃。
  2. 持久化成本: 如果启用了持久化机制(如快照或日志持久化),存储大量的数据会导致持久化操作变得耗时,并可能影响系统的响应性能。
  3. 数据传输开销: 当数据量较大时,在网络传输数据时可能会引起显著的网络开销,影响数据传输的效率和速度。
  4. 查询性能: 对大型 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:

  1. 原子性(Atomicity)
    事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。回滚可以用回滚日志(Undo Log)来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。
  2. 一致性(Consistency)
    数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。
  3. 隔离性(Isolation)
    一个事务所做的修改在最终提交以前,对其它事务是不可见的。
  4. 持久性(Durability)
    一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

3.隔离级别

  • 未提交读(READ UNCOMMITTED)
    事务中的修改,即使没有提交,对其它事务也是可见的。
  • 提交读(READ COMMITTED)
    一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。
  • 可重复读(REPEATABLE READ)
    保证在同一个事务中多次读取同一数据的结果是一样的。
  • 可串行化(SERIALIZABLE)
    强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。

你可能感兴趣的:(面试,职场和发展)