当前位置: 首页 > news >正文

java 面试八股集锦

MySQL篇

1.聚集索引的数据和索引放在一起,一个表只能有一个聚集索引,适合范围查询
非聚集索引的数据和索引分离,索引指向数据,一个表可以有多个非聚集索引,适合精确查询

2.B+ tree的优势(和哈希表,二叉树对比):高度低,磁盘io次数少; 查询高效,而且效率稳定,时间复杂度低

3.索引是一种数据结构,可以提高检索效率,降低io成本,减少cpu消耗

4.索引的缺点:执行增删改操作时效率变低,占用额外存储空间

5.索引失效的情况:模糊匹配的时候以%开头; 对列进行函数运算或表达式计算;字符串不加引号; or连接的条件,一边有索引一边无索引;

6.唯一索引:加速查询 + 列值唯一(可以有 NULL)。
联合索引:多列值组成一个索引,用于组合搜索,效率大于索引合并

索引类型(按照物理结构):聚簇索引、非聚簇索引。
索引类型(按照功能分类):主键索引、唯一索引、全局索引、复合索引、普通索引。

7.事务四大特性(acid): 原子性(回滚日志实现),一致性(通过其他三者实现),持久性(重做日志实现,隔离性(锁机制和mvcc实现)

8.事务隔离级别: 读未提交,读已提交,可重复读,串行化; mysql是默认可重复读

9.mysql默认存储引擎:innodb,综合处理能力和性能最好
innodb支持事务,myisam,memory不支持
innodb支持行级锁和表锁,其他两个只有表级锁
innodb支持外键,其他的不支持
innodb有崩溃恢复机制,其他的没有

innoDB适合高并发写操作;myisam适合读多写少的场景 memory用内存存储数据,访问速度快但数据容易丢失
10.EXPLAIN 命令可以分析 SQL 的 执行计划

11.mysql连接分为内连接和外连接,
内连接只返回两张表中都匹配的记录;
外连接分为左外连接和右外连接:
左外连接返回左表所有行,右表没匹配到的记录用null填充,
右外连接返回右表所有行,左表没匹配到的记录用null填充

12.count(1)、count() 与 count(列名) 的区别?:count(1)、count() 都是统计所有行数,COUNT(列名)会忽略值为null的行

13.覆盖索引是什么?: 查询的所有字段都能从索引本身获取,不需要回表。可以减少一次主键查询,性能更高

14.回表是什么: 通过二级索引(除了主键索引之外的索引)找到主键,再通过主键索引(聚簇索引)查找数据的过程。

15.最左前缀原则: 查询条件必须从索引最左边的列开始匹配,并且连续匹配,索引才会生效. 如果中间某个列不在查询条件中,后面的索引会失效

16.drop、delete 与 truncate 的区别?
DROP 用来删除整张表,包括表结构,不能回滚。

TRUNCATE 用于清空表中的所有数据,但会保留表结构,不能回滚。

DELETE 用来删除行,可以带 WHERE 条件,可以回滚。

17.sql查询的执行顺序: 先执行 FROM 确定主表,再执行 JOIN 连接,然后 WHERE 进行过滤,接着 GROUP BY 进行分组,HAVING 过滤聚合结果,SELECT 选择最终列,ORDER BY 排序,最后 LIMIT 限制返回的行数

  1. InnoDB 是如何存储数据的?
    InnoDB 的数据按行存储在页(16KB)中,页组成段,段存放在表空间中。
    数据通过聚集索引存储,二级索引存储主键引用。
    InnoDB 支持事务和 MVCC,使用 Redo Log 和 Undo Log 实现崩溃恢复和事务回滚,同时通过缓冲池加速磁盘读写。

  2. Hash 索引与 BTree 索引有什么区别?
    Hash 索引基于哈希表实现,支持等值查询,查询速度快,不支持范围查询和排序操作;
    BTree 索引基于平衡树结构,支持等值查询、范围查询和排序操作,适合大多数查询场景

  3. SQL 聚合函数有哪些?
    COUNT、SUM、AVG、MIN、MAX等,用于对数据集进行汇总和统计分析。


Redis篇

1.缓存穿透: 请求的数据在缓存和数据库中都不存在,导致所有请求打到数据库; 解决:布隆过滤器,缓存空值,在接口层进行校验,过滤无效请求

缓存击穿: 热点key过期,大量请求直接打到数据库; 解决:互斥锁,逻辑过期

缓存雪崩:同一时间内大量key过期或者redis服务宕机导致所有请求访问数据库; 解决:随机过期时间,分散key过期; 使用多级缓存; 使用redis集群和主从哨兵机制

2.如何实现可重入锁?:可重入锁指的是在一个线程中可以多次获取同一把锁,实现思路是: 线程在获取锁的时候判断是否为自己的锁,如果是,不再重新获取锁, 而是计数加一,释放锁计数减一

3.分布式锁怎么实现?使用setnx命令(建议使用lua脚本,保证解锁操作的原子性)或者redission框架的分布式锁

4.先操作缓存还是先操作数据库?:先操作数据库, 再删除缓存

5.使用redis的哪种数据结构实现点赞/关注/签到功能?:Set, Set能快速添加和删除,并且可以去重
Set还可以用于获取交集,并集,差集,比如共同好友(交集), 好友推荐(差集)

6.排行榜怎么实现?sorted set有序集合,可以按分数进行排序

7.redis为什么快:单线程,没有线程切换和锁竞争; 基于内存,速度快,使用io多路复用模型

8.redis持久化机制: rdb和aof, rdb定期将内存中的数据生成快照并写入文件中,aof每执行一次命令就把命令追加到文件里

9.RDB 创建快照时会阻塞主线程吗?:不会,bgsave命令fork 出一个子进程,不会阻塞 Redis 主线程

10.如何选择 RDB 和 AOF?:对数据安全性要求不高选择rdb,否则选择aof; rdb恢复数据的速度更快,不用像aof一样依次执行命令

11.redis事务:用于保证一组命令的原子性,不支持回滚,使用 MULTI (事务的开始)和EXEC(事务的结束)命令

12.redis的数据过期策略:惰性删除(访问key,检查是否过期,过期就删除), 定期删除(每隔一段时间检查key并删除),内存淘汰(达到阈值删除)

13.Redis 哨兵机制: 是 Redis 实现高可用的方案,负责监控主从节点、自动故障转移和通知客户端。当主节点宕机时,哨兵会通过投票机制选出新的主节点,并让其他从节点跟随它,同时通知客户端更新连接。能够避免单点故障,保证 Redis 集群自动恢复

14.Redis主从复制(同步)是什么? 主从复制是将一台 Redis 服务器的数据实时复制到其他 Redis 服务器的机制。主节点负责写,从节点负责读,复制分为全量复制和增量复制, 主从复制能够避免单节点redis故障,即使有一台服务器宕机,其他服务器依然可以工作

全量复制: 将主节点当前所有的数据完整地复制到从节点,从节点会丢弃自己原有的数据,直接用主节点的数据覆盖

增量复制: 在全量复制完成后,主节点将新增的写命令实时发送给从节点(只请求主节点产生的新数据),从节点按顺序执行,实现持续同步


Java 集合

1.Hashmap和Hashtable的区别?

  1. Hashmap线程不安全, Hashtable线程安全,因为Hashtable的方法被synchronized修饰

  2. Hashmap的效率更高,因为没加锁.

  3. Hashmap允许key和value为null, Hashtable不允许

  4. 初始容量和每次扩容的大小不同:① 创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充容量变为原来的 2n+1。HashMap 默认的初始化大小为 16。之后每次扩充容量变为原来的 2 倍。② 创建时如果给定了容量初始值, Hashtable 会直接使用给定的大小,但 HashMap 会将其扩充为 2 的幂次方大小

  5. HashMap 和 HashSet 区别
    HashMap基于 哈希表实现,用键值对存储数据
    HashSet基于 HashMap 实现,只存储键(key),值(value)用一个固定的常量对象占位
    HashMap存储键值对, 键不可重复,值可以重复; HashSet 储存单一元素, 元素不能重复

  6. HashMap 的底层实现
    底层数据结构: JDK 1.8 之前:数组 + 链表, JDK 1.8 及以后:数组 + 链表 + 红黑树
    HashMap通过 key 的 hash 值定位数组索引,将元素存放在对应的桶中。如果桶里没有元素,就直接插入;如果有元素且 key 相同,就覆盖 value;如果 key 不同,则挂到链表尾部或者红黑树中,来解决哈希冲突。当链表长度超过阈值且数组容量达到一定大小时,链表会转为红黑树,以提升查找效率. 当元素数量超过数组长度 × 负载因子(默认 0.75)时触发扩容,会重新计算所有元素索引。

  7. HashMap 为什么线程不安全?
    原因: 并发操作可能破坏内部数据结构,例如多线程同时执行 put 操作时,会造成数据覆盖问题, 多线程扩容可能导致死循环或环形链表。多线程并发修改时,size计数可能出现错误。解决方式是使用 synchronizedMap 或 ConcurrentHashMap。

  8. ConcurrentHashMap是什么
    ConcurrentHashMap 是 Java 提供的线程安全哈希表。JDK1.7 使用 分段锁 Segment实现,写操作锁定对应段,读操作无锁;JDK1.8采用 数组 + 链表/红黑树 + CAS + synchronized 机制实现,写操作通过 CAS 或同步锁保证线程安全,读操作无锁且通过 volatile 保证可见性,扩容也使用 CAS 保证多线程安全。它支持高并发读写,性能远高于 Hashtable 和 synchronizedMap,同时在链表长度过长时会转红黑树,以提升最坏情况下的查找效率。


Java并发

  1. 如何创建线程池?
    方式一:通过 ThreadPoolExecutor 构造函数创建, 可以自定义核心线程数、最大线程数、阻塞队列和拒绝策略,更安全、更灵活。
    方式二:通过 Executors 工具类创建,非常简便

  2. 什么是线程和进程?
    进程是操作系统资源分配的基本单位,线程是 CPU 调度的基本单位。一个进程可以包含多个线程,线程之间共享进程的内存和资源,但有自己的栈和寄存器。进程切换开销大、通信成本高,线程切换开销小、通信方便,但线程之间需要注意同步问题。

  3. 如何创建线程?
    继承Thread类、实现Runnable接口、实现Callable接口、使用线程池、使用CompletableFuture类

  4. 线程的生命周期和状态
    Java 线程有 6 种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 和 TERMINATED。
    NEW 是新建未启动,RUNNABLE 表示等待 CPU 调度,BLOCKED 等待锁,WAITING 无限期等待唤醒,TIMED_WAITING 限时等待自动唤醒,TERMINATED 表示终止状态。

  5. 可以直接调用 Thread 类的 run 方法吗?
    可以直接调用, 但这样不会以多线程的方式执行,而是在当前线程中执行 run 方法的代码。调用 start() 方法方可启动线程并使线程进入就绪状态

  6. 什么是线程死锁?
    多个线程在执行过程中,由于竞争资源而造成的互相等待的现象,导致它们都无法继续执行下去。
    产生的四个必要条件(缺一不可)

  7. 互斥:资源一次只能被一个线程占用。

  8. 占有且等待:一个线程至少持有一个资源,同时等待其他线程持有的资源。

  9. 不可抢占:资源在未使用完之前,不能被其他线程强行抢占。

  10. 循环等待:多个线程形成首尾相接的等待资源关系。

  11. 怎样避免死锁?
    • 1. 按固定顺序申请锁,避免循环等待;
    • 2. 一次性申请所有资源;
    • 3. 设置锁超时时间
    • 4. 减少锁的持有时间
    • 5. 使用更高级的并发工具,如 ConcurrentHashMap、BlockingQueue、Semaphore 等

  12. volatile 关键字是什么
    volatile 是 Java 中的一个关键字,用来保证变量的可见性和有序性,但不保证原子性。
    可见性: 当一个线程修改了 volatile 变量的值,新的值会立即刷新到主内存。其他线程在读取该变量时,会直接从主内存读取最新值
    有序性: Volatile能阻止指令重排, 确保变量的读写操作按代码顺序执行

  13. synchronized 是什么?有什么用?
    synchronized 是 Java 内置的锁,用于保证多线程对共享资源的互斥访问 (保证线程安全), 可以修饰方法或代码块, 确保在任意时刻只有一个线程执行

synchronized 的使用方式:

  1. 修饰实例方法

  2. 修饰静态方法

  3. 修饰代码块

  4. synchronized 和 volatile 有什么区别?
    synchronized 关键字和 volatile 关键字是两个互补的存在,而不是对立的存在!
    • volatile 是轻量级同步,性能肯定比synchronized更好 。但是 volatile只能修饰变量, 而 synchronized 关键字可以修饰方法以及代码块 。
    • volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。
    • volatile用于解决变量在多个线程之间的可见性,而 synchronized解决的是多个线程之间访问资源的同步性。

  5. ThreadLocal 有什么用?
    线程隔离: 为每个线程创建一个独立的变量副本,使每个线程可以独立地操作自己的副本,而不影响其他线程,也就是线程隔离
    用于保存线程上下文信息: 如数据库连接、用户id

  6. 什么是线程池?
    一种线程复用机制,在程序启动时创建一定数量的线程,线程执行完任务后返回线程池等待下一个任务

作用:

  1. 减少线程创建和销毁的开销, 降低资源消耗

  2. 可以更好的管理线程, 统一管理线程的生命周期

  3. 提高响应速度: 线程池里会维护一定数量的核心线程,任务来了之后可以直接由这些线程执行,不需要新建线程

  4. 使用多线程会带来什么问题,怎么解决?:
    问题:
    线程安全:比如并发修改导致数据不一致。
    死锁:多个线程互相持有对方需要的锁。
    上下文切换:线程切换开销影响性能。
    资源竞争:如锁竞争导致线程阻塞。

解决:
线程安全:用synchronized、Lock(如ReentrantLock)保证同步;使用原子类(AtomicInteger)或并发集合(ConcurrentHashMap)。
死锁:避免嵌套锁、按顺序加锁、使用tryLock设置超时。
减少上下文切换:使用无锁并发(CAS)、线程池复用线程。

  1. 线程池常见参数有哪些?
    ThreadPoolExecutor 的常见参数包括:核心线程数、最大线程数、非核心线程空闲存活时间及单位、任务队列、线程工厂和拒绝策略

15.线程池处理任务的流程:

  1. 提交任务;
  2. 如果核心线程空闲,则直接执行;
  3. 核心线程满了则入队列等待;
  4. 队列满了且线程数未达最大值,则创建非核心线程执行;
  5. 队列满了且线程数到达最大值,则触发拒绝策略;
  6. 非核心线程空闲超过 keepAliveTime 会被回收

计算机网络

1.HTTP/1.0、HTTP/1.1、HTTP/2.0、HTTP/3.0 的区别?
HTTP/1.0 → 是短连接,每次请求都要建立 TCP,效率低下
HTTP/1.1 → 是长连接,一个TCP连接可以发送多次请求,但有队头阻塞问题
HTTP/2.0 → 实现了多路复用,一个TCP连接可以并发处理多个请求, 解决了1.1的请求队头阻塞,但底层仍存在TCP的队头阻塞,引入了二进制传输 + 头部压缩
HTTP/3.0 → 基于 QUIC,使用UDP代替TCP, 彻底解决 TCP 队头阻塞,支持 0-RTT,更快更安全。
2. HTTP 常见状态码有哪些?
• 200 OK:请求成功。
• 201 Created: POST 新建资源成功。
• 301 永久重定向:资源位置永久改变,浏览器会缓存
• 302 临时重定向:临时跳转,常见于登录后跳转
• 304 Not Modified:协商缓存,资源未修改,用于优化性能
• 400 Bad Request:请求参数错误
• 401 Unauthorized:未认证或 token 无效
• 403 Forbidden:认证了但没有权限
• 404 Not Found:资源不存在
• 500 Internal Server Error:服务端程序错误。
• 502 Bad Gateway:网关/代理收到无效响应(常见于 Nginx)
• 503 Service Unavailable:服务不可用,通常是服务过载或维护

  1. HTTP 请求头中包含什么?
    大体可以分为四类: 通用信息(Host、User-Agent、Accept 等)、缓存与来源控制(Cache-Control、Referer)、认证与安全(Authorization、Cookie)、以及请求体相关(Content-Type、Content-Length)。

  2. HTTP 是基于 TCP 还是 UDP?
    HTTP/1.x 和主流 HTTP/2 都基于 TCP;而 HTTP/3 基于 UDP

  3. HTTP 长连接 vs. 短连接的区别是?
    短连接:请求一次建立一次连接,用完就断;
    长连接:多个请求复用一个连接,性能更好

  4. 从「敲下一个 URL」到「页面出现在屏幕」整条链路全景
    浏览器解析 URL 并查缓存 → DNS 解析域名 → TCP/HTTPS 握手建立连接 → 发送 HTTP 请求 → 服务器处理并返回响应 → 浏览器解析 渲染→ 断开链接 四次挥手

  5. GET 与 POST 有什么区别?
    GET 用于获取数据,参数在 URL,幂等且可缓存;
    POST 用于提交数据,参数在请求体,非幂等,不易缓存。
    GET 适合查询,POST 适合创建/更新资源。

幂等(多次请求结果相同,不改变服务器状态)
非幂等(多次提交可能创建多条数据或触发多次操作)

8.HTTP vs. HTTPS 有什么区别?
HTTP以明文形式传输,传输的数据可能会被窃听、篡改、仿造。
HTTPS在 HTTP 上加了 TLS/SSL 加密。更安全, 适合敏感信息传输

  1. WebSocket 简介 & 与 HTTP 的核心区别
    WebSocket 是基于 TCP 的全双工长连接协议,建立连接后客户端和服务器可以互相发送数据,适合实时高频场景。
    HTTP 是单向请求-响应协议,客户端必须先发起请求,服务器才能响应。
    WebSocket数据传输开销更小,效率更高。”

  2. TCP 与 UDP 的区别?
    TCP 是面向连接、可靠的传输协议,保证数据完整、顺序、无重复,但开销大,适合需要可靠传输的场景, 比如文件传输, 远程登录
    UDP 是无连接、不可靠协议,开销小、传输快,适合对实时性要求高、能容忍少量丢包的场景, 比如视频直播、在线游戏、语音通信

  3. TCP 的三次握手
    第一次握手:客户端向服务器端发送SYN,确认客户端的发送没问题。
    第二次握手:服务器向客户端发送SYN和ACK包,确认服务器的发送与接收没问题
    第三次握手:客户端最后回复一个ACK包,确认客户端的接收没问题。

  4. 数据包在网络中传输的过程

  5. 发送方将应用数据封装成数据包,添加源地址,发送方法,传输协议类型,目的地址等

  6. 选择路由转发数据包,发送到目标主机

  7. 接收端解密数据包,恢复成原始数据

  8. ip地址的划分
    IP地址主要分为 IPv4 和 IPv6,日常使用更多的是 IPv4。IPv4 通过“网络位”和“主机位”来区分,用于实现网络分层管理和设备寻址。
    IPv4 按类别划分为 A/B/C/D/E 类:
    • A 类(1.0.0.0–126.255.255.255)用于大型网络,网络位 8 位,主机位 24 位;
    • B 类(128.0.0.0–191.255.255.255)用于中型网络,网络位 16 位,主机位 16 位;
    • C 类(192.0.0.0–223.255.255.255)用于小型网络,网络位 24 位,主机位 8 位;
    • D 类用于组播,E 类为保留地址。
    现代网络更常用 无类别域间路由,通过“IP 地址/子网掩码长度”表示,例如 192.168.1.0/24,其中前 24 位为网络位,后 8 位为主机位,可灵活调整网络和主机数量,提高地址利用率。

http://www.dtcms.com/a/334676.html

相关文章:

  • K8S HPA 弹性水平扩缩容 Pod 详解
  • 西门子SMART PLC监控时间戳问题BUG修复
  • Cursor执行命令卡顿解决办法(Cursor卡住、Cursor命令卡住、Cursor执行慢、Cursor执行命令慢)改成以管理员身份运行就好!!!
  • 《探索IndexedDB实现浏览器端UTXO模型的前沿技术》
  • 【CPP】自己实现一个CPP小工具demo,可以扩展其他选项
  • homebrew 2
  • pytorch例子计算两张图相似度
  • 创建maven module中的override
  • Maven下载和配置-IDEA使用
  • 自动化测试的下一站:AI缺陷检测工具如何实现“bug提前预警”?
  • uniapp跨端适配方案
  • Qt 动态属性(Dynamic Property)详解
  • SDN安全开发环境中常见的框架,工具,第三方库,mininet常见指令介绍
  • 【基础-判断】HarmonyOS提供了基础的应用加固安全能力,包括混淆、加密和代码签名能力
  • 守护品质安全,防伪溯源系统打造全链路信任体系
  • 物联网 (IoT) 的顶级硬件平台
  • IEEEtaes.cls解析
  • python---模块
  • 防御保护15
  • YOLOv8环境配置命令
  • GCN图卷积神经网络的Pytorch实现
  • Azure AI Search 探索总结
  • 数据库索引视角:对比二叉树到红黑树再到B树
  • 【计算机视觉与深度学习实战】03基于Canny、Sobel和Laplacian算子的边缘检测系统设计与实现
  • DeepSeek-R1-深度解析-通过强化学习激励大语言模型的推理能力
  • Spring AI 玩转工具调用:模型帮你精确设闹钟
  • 九尾狐未来机械锂晶核
  • 盲盒抽谷机小程序系统开发:从0到1的完整方法论
  • 《从入门到精通:Kafka核心原理全解析》
  • 医院管理中的PythonAI编程:资源调配、质量监控、成本控制、医保监管与科研转化