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

场景以及八股复习篇

文章目录

  • MySQL
      • **1. MVCC(多版本并发控制)**
      • **2. 小表驱动大表,哪个表建索引?**
      • **3. 索引失效场景**
      • **4. 排序索引优化**
      • **5. EXPLAIN有效字段**
      • **6. 视图(View)**
      • **7. 触发器(Trigger)**
      • **8. 存储过程与函数**
      • **9. MySQL主从复制及延迟处理**
      • **10. ACID实现**
      • **11. 数据库备份与恢复**
      • **12. 死锁及处理**
      • **13. 分区表**
      • **14. 优化器使用**
      • **15. JOIN与子查询性能比较**
      • **16. 二进制日志(binlog)**
      • **17. 幻读及解决**
  • RabbitMQ
      • **1. 消息队列中的消息可靠性保证**
        • **(1)生产端可靠性**
        • **(2)MQ 服务端可靠性**
        • **(3)消费端可靠性**
        • **(4)异常处理与监控**
      • **2. Virtual Host(虚拟主机)作用**
        • **定义**
        • **核心作用**
        • **使用场景**
      • **3. 消息确认模式**
        • **自动确认(Auto Ack)**
        • **手动确认(Manual Ack)**
        • **选择建议**
      • **4. 消费者组(Consumer Group)**
        • **定义**
        • **核心机制**
        • **注意事项**
      • **总结**
  • Nginx
      • Nginx主进程如何重新加载配置文件
  • Maven
      • **1. Clean 生命周期**
      • **2. Default 生命周期(Build 生命周期)**
      • **3. Site 生命周期**
      • **总结对比**
      • **补充说明**
  • JVM
      • **JVM 组件有哪些?**
      • **什么是逃逸分析(Escape Analysis)?**
        • **对象逃逸的三种状态**:
        • **逃逸分析的价值**:
        • **触发条件**:
        • **示例**:
      • **对永久代(PermGen)和元空间(Metaspace)的看法**
        • **永久代(PermGen)**(JDK 8 之前):
        • **元空间(Metaspace)**(JDK 8+):
        • **迁移建议**:
      • **JIT 是什么?**
        • **核心功能**:
        • **JIT 分类**:
        • **JIT 优化示例**:
      • **如何监控 JVM 性能?**
        • **常用工具和命令**:
        • **监控指标**:
      • **JVM 如何实现线程同步?**
        • **核心机制**:
        • **生产者-消费者模式示例**:
      • **死锁检测的命令**
        • **常用命令**:
        • **预防死锁**:
      • **主流的垃圾回收器和算法**
        • **垃圾回收算法**:
        • **主流垃圾回收器**:
        • **选择建议**:
  • JUC
      • **你对 Executor 框架的了解**
      • **你对 JUC 的了解**
      • **谈谈 Callable 和 Future 用法**
      • **CountDownLatch 应用举例**
      • **CyclicBarrier 应用举例**
      • **Atomic 常见使用**
      • **阻塞队列有哪些实现?你了解 AQS 吗?谈一谈**
        • **阻塞队列实现**:
        • **AQS(AbstractQueuedSynchronizer)**
      • **ConcurrentHashMap 和 Hashtable 区别**

MySQL

1. MVCC(多版本并发控制)

实现原理

  • Undo Log:记录数据修改前的版本,形成版本链。每次修改生成新版本,旧版本通过指针连接。
  • Read View:事务执行快照读时生成的视图,包含活跃事务ID列表(m_ids)、最小事务ID(min_trx_id)、最大事务ID(max_trx_id)和当前事务ID(creator_trx_id)。
  • 可见性判断:通过对比记录的事务ID(DB_TRX_ID)和Read View,决定版本是否可见。

解决的问题

  • 脏读:只能读已提交的数据版本。
  • 不可重复读:同一事务内多次读取结果一致(基于相同Read View)。
  • 幻读:通过间隙锁(Gap Lock)和版本链防止。

2. 小表驱动大表,哪个表建索引?

  • 小表驱动大表:将小表作为驱动表(外层循环),大表作为被驱动表(内层循环)。
  • 索引建议
    • 大表的连接字段:在大表的连接列上建立索引,减少扫描量。
    • 小表的过滤字段:如果小表有筛选条件(如WHERE),可在小表的过滤列建索引。
  • 示例
    SELECT * FROM small_table s
    JOIN large_table l ON s.id = l.small_id;
    
    • large_table.small_id 上建索引。

3. 索引失效场景

场景原因示例
函数操作索引列被函数处理,无法匹配WHERE YEAR(create_time) = 2024
OR 条件若OR条件涉及非索引列,索引失效WHERE id = 1 OR name = 'A'
!= / NOT IN跳过索引,全表扫描WHERE status != 1
模糊匹配左模糊(%abc)无法使用索引WHERE name LIKE '%abc'
类型转换隐式转换导致索引失效WHERE id = '123'(id为int)

4. 排序索引优化

  • 原则
    1. 排序字段与索引列顺序一致ORDER BY a, b → 索引 (a, b)
    2. 避免混合升序/降序:索引顺序需与排序方向一致。
    3. 覆盖索引:排序字段和查询字段都在同一索引中。
  • 示例
    CREATE INDEX idx_name_age ON users(name, age);
    SELECT name, age FROM users ORDER BY name, age; -- 使用索引
    

5. EXPLAIN有效字段

字段含义优化建议
type访问类型(ALL < index < range < ref < eq_ref < const)优先使用 ref/eq_ref
key实际使用的索引检查是否命中预期索引
rows预计扫描行数越小越好
Extra额外信息Using filesort(需优化排序)、Using temporary(需优化分组)

6. 视图(View)

定义:虚拟表,基于SQL查询结果。
优点

  • 简化复杂查询:隐藏复杂逻辑。
  • 数据安全:限制用户访问敏感数据。
  • 逻辑独立性:表结构变更不影响视图。
    缺点
  • 性能开销:视图可能引发全表扫描。
  • 更新限制:仅支持简单视图的更新(无聚合函数、DISTINCT等)。

7. 触发器(Trigger)

作用:在特定事件(INSERT/UPDATE/DELETE)发生时自动执行。
语法示例

CREATE TRIGGER before_insert_user
BEFORE INSERT ON users
FOR EACH ROW
BEGINSET NEW.create_time = NOW();
END;

使用场景

  • 数据校验(如自动填充时间戳)。
  • 审计日志(记录操作历史)。
  • 注意事项:避免复杂逻辑,防止触发器嵌套导致性能问题。

8. 存储过程与函数

存储过程

  • 可包含多个SQL语句,支持输入/输出参数。
  • 用于封装业务逻辑(如批量操作)。
    函数
  • 必须返回单个值,可在SQL语句中直接调用。
  • 用于计算(如 SELECT my_function())。
    区别
    | 特性 | 存储过程 | 函数 |
    |------|----------|------|
    | 返回值 | 多个参数(IN/OUT) | 单个返回值 |
    | 调用方式 | CALL proc() | SELECT func() |
    | 事务支持 | 支持 | 不支持 |

9. MySQL主从复制及延迟处理

实现步骤

  1. 主库开启binlog:配置 server-idlog-bin
  2. 从库配置:设置 server-id 并连接主库。
  3. 启动复制线程START SLAVE;
    延迟处理
  • 优化主库负载:减少大事务和锁竞争。
  • 调整同步方式:异步→半同步(semi-sync)减少延迟。
  • 监控延迟SHOW SLAVE STATUS\G 中的 Seconds_Behind_Master

10. ACID实现

  • 原子性(Undo Log):通过回滚日志实现事务回滚。
  • 一致性(约束+事务):通过约束(主键、外键)和事务机制保证。
  • 隔离性(锁/MVCC):InnoDB通过行锁和MVCC实现。
  • 持久性(Redo Log):通过重做日志将数据刷盘。

11. 数据库备份与恢复

备份方式

  • 物理备份(如 xtrabackup):直接复制数据文件,速度快。
  • 逻辑备份(如 mysqldump):导出SQL语句,灵活但慢。
    恢复步骤
  1. 物理备份恢复:停止MySQL,替换数据文件。
  2. 逻辑备份恢复:导入SQL文件(mysql -u root < backup.sql)。

12. 死锁及处理

死锁条件

  1. 互斥
  2. 请求与保持
  3. 不可剥夺
  4. 循环等待
    预防方法
  • 按固定顺序访问资源
  • 设置超时innodb_lock_wait_timeout)。
    处理
  • 查看死锁日志SHOW ENGINE INNODB STATUS\G
  • 手动终止事务KILL <thread_id>;

13. 分区表

实现方式

  • 范围分区:按数值范围划分(如日期)。
  • 列表分区:按枚举值划分。
  • 哈希分区:按哈希函数值划分。
  • 键分区:类似哈希,但由MySQL自动管理。
    示例
CREATE TABLE sales (id INT,sale_date DATE
)
PARTITION BY RANGE (YEAR(sale_date)) (PARTITION p2023 VALUES LESS THAN (2024),PARTITION p2024 VALUES LESS THAN (2025)
);

14. 优化器使用

  • 统计信息ANALYZE TABLE 更新表统计信息,帮助优化器选择最优执行计划。
  • 索引建议:通过 EXPLAIN 分析,添加缺失的索引。
  • 查询重写:避免隐式转换、减少子查询嵌套。

15. JOIN与子查询性能比较

  • JOIN:通常更快,尤其是当有合适索引时。
    SELECT u.name, o.order_id
    FROM users u
    JOIN orders o ON u.id = o.user_id;
    
  • 子查询:适合嵌套查询,但可能导致多次扫描。
    SELECT name FROM users WHERE id IN (SELECT user_id FROM orders);
    

建议:优先使用JOIN,尤其在大数据量场景。


16. 二进制日志(binlog)

作用

  • 数据恢复:通过日志重放恢复误删数据。
  • 主从复制:从库应用主库的binlog事件。
  • 审计:记录所有数据库变更。
    格式
  • STATEMENT:记录SQL语句。
  • ROW:记录行级变更。
  • MIXED:混合模式。

17. 幻读及解决

定义:事务中两次查询结果集数量不一致(新增/删除记录)。
解决方案

  • 可重复读(RR)隔离级别:InnoDB通过间隙锁(Gap Lock)防止幻读。
  • 串行化(Serializable):完全锁表,但性能差。
  • 显式锁:使用 SELECT ... FOR UPDATE 锁定范围。

RabbitMQ

1. 消息队列中的消息可靠性保证

在 RabbitMQ 中,消息可靠性保证涉及 生产端MQ 服务端消费端 的协同配合,核心机制包括:

(1)生产端可靠性
  • 消息持久化

    • 发送消息时,设置 deliveryMode=2(持久化),确保消息写入磁盘而非仅内存。
    • 队列需声明为持久化(durable=true),防止队列在 RabbitMQ 重启时丢失。
    • 示例
      // 声明持久化队列
      channel.queueDeclare("my_queue", true, false, false, null);
      // 发送持久化消息
      AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().deliveryMode(2).build();
      channel.basicPublish("", "my_queue", props, "Hello, RabbitMQ!".getBytes());
      
  • 生产者确认(Confirm)机制

    • 开启 publisher_confirm,确保消息成功写入队列后才返回 ACK。
    • 若未收到 ACK,生产者可重试发送消息(需配合幂等性设计)。
    • 示例
      channel.confirmSelect(); // 启用确认模式
      if (!channel.waitForConfirms()) {// 重试发送消息
      }
      
(2)MQ 服务端可靠性
  • 持久化存储

    • 默认情况下,消息存储在内存中,重启后丢失。必须配置磁盘持久化(如 Kafka 的日志文件)。
    • RabbitMQ 支持 Lazy Queues(惰性队列),消息直接落盘,避免内存积压导致 PageOut 阻塞。
  • 高可用架构

    • 镜像队列:通过集群部署,将队列复制到多个节点,防止单点故障。
    • 集群部署:结合主从节点和自动故障转移(如 Kafka 的 ISR 列表),确保数据冗余和可用性。
(3)消费端可靠性
  • 手动确认(ACK)机制

    • 消费者处理完消息后,手动发送 basic.ack,确保消息不会被 RabbitMQ 过早删除。
    • 若消费者处理失败(如宕机),消息会被重新投递到其他消费者。
    • 示例
      DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");try {processMessage(message); // 处理消息channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); // 手动确认} catch (Exception e) {// 记录日志或重试,不确认消息}
      };
      channel.basicConsume("my_queue", false, deliverCallback, consumerTag -> {});
      
  • 幂等性设计

    • 消费者需确保重复消费不影响业务逻辑(如数据库唯一约束、去重 ID)。
    • 示例
      -- 数据库插入时通过唯一键避免重复
      INSERT INTO orders (id, user_id, product) VALUES (?, ?, ?) ON CONFLICT (id) DO NOTHING;
      
(4)异常处理与监控
  • 重试机制
    • 生产端发送失败时,通过重试策略(如指数退避)重新发送消息。
  • 监控告警
    • 使用 Prometheus + Grafana 监控消息堆积、确认延迟等指标,及时发现异常。

2. Virtual Host(虚拟主机)作用

定义

Virtual Host 是 RabbitMQ 中的逻辑隔离单元,用于将不同的应用或用户资源(队列、交换机、绑定关系)隔离开,避免命名冲突和权限泄露。

核心作用
  1. 资源隔离
    • 不同 vhost 的队列和交换机互不干扰,适合多租户场景(如生产环境 vs 测试环境)。
  2. 权限管理
    • 用户权限绑定到特定 vhost,限制其只能访问所属 vhost 的资源。
    • 示例
      # 创建 vhost
      rabbitmqctl add_vhost /production
      # 创建用户并绑定权限
      rabbitmqctl add_user dev_user password
      rabbitmqctl set_permissions -p /production dev_user ".*" ".*" ".*"
      
  3. 灵活配置
    • 每个 vhost 可独立配置参数(如消息 TTL、死信队列策略)。
使用场景
  • 多项目隔离:不同业务系统使用独立 vhost,避免资源冲突。
  • 环境隔离:开发、测试、生产环境分别使用不同 vhost,防止误操作。
  • 租户管理:SaaS 应用中,为每个租户分配独立 vhost,保障数据安全。

3. 消息确认模式

自动确认(Auto Ack)
  • 特点
    • 消息投递给消费者后立即标记为已确认,无需消费者显式确认。
    • 优点:低延迟,适合快速处理且容忍少量消息丢失的场景。
    • 缺点:若消费者处理失败(如宕机),消息会丢失。
  • 适用场景:日志收集、实时性要求高的非关键业务。
手动确认(Manual Ack)
  • 特点
    • 消费者需显式调用 basic.ack 确认消息处理完成。
    • 优点:确保消息不丢失,适合关键业务(如订单支付)。
    • 缺点:实现复杂,需处理异常重试。
  • 关键配置
    // 关闭自动确认
    channel.basicConsume("my_queue", false, deliverCallback, consumerTag -> {});
    
选择建议
  • 优先使用手动确认:保障消息可靠性,尤其在消费逻辑复杂或处理时间较长时。
  • 自动确认的替代方案:若使用自动确认,需确保消费者逻辑健壮(如快速处理、无宕机风险)。

4. 消费者组(Consumer Group)

定义

消费者组是指多个消费者共享同一个队列,通过负载均衡分担消息处理任务。RabbitMQ 通过 轮询调度 将消息分发给组内消费者。

核心机制
  1. 负载均衡

    • RabbitMQ 按轮询方式将消息分发给在线消费者,避免单点过载。
    • 示例
      // 定义两个消费者监听同一队列
      @Component
      @RabbitListener(queues = "shared_queue")
      public class ConsumerA {@RabbitHandlerpublic void receive(String message) {System.out.println("ConsumerA: " + message);}
      }@Component
      @RabbitListener(queues = "shared_queue")
      public class ConsumerB {@RabbitHandlerpublic void receive(String message) {System.out.println("ConsumerB: " + message);}
      }
      
  2. 高可用性

    • 若某个消费者宕机,消息会被重新投递给其他消费者,确保任务不丢失。
    • 需配合 手动确认消息重试机制,防止消息因处理失败而丢失。
  3. 扩展性

    • 动态增加消费者实例,提升消息处理能力,适应流量高峰。
注意事项
  • 避免重复消费
    • 手动确认需确保消费者在处理完消息后才发送 basic.ack,否则消息可能被重复投递。
  • 幂等性设计
    • 即使消息重复投递,消费者应能识别并忽略重复请求(如通过唯一 ID 校验)。

总结

模块关键点
消息可靠性持久化(队列/消息)、生产者确认、消费者手动确认、集群镜像、幂等性设计。
Virtual Host资源隔离、权限管理、环境隔离、租户管理。
消息确认模式自动确认(低延迟) vs 手动确认(高可靠性),需结合业务场景选择。
消费者组负载均衡、高可用、动态扩展,需配合手动确认和幂等性保障可靠性。

Nginx

Nginx主进程如何重新加载配置文件

SIGHUP

Maven

Maven 的三种生命周期(CleanDefaultSite)分别负责项目构建的不同阶段,以下是它们的详细作用和场景:


1. Clean 生命周期

作用清理项目,删除之前的构建产物,确保构建环境的整洁。

  • 核心阶段
    • pre-clean:在清理前执行,通常用于执行自定义的清理前操作(如备份配置文件)。
    • clean删除目标目录(如 target)中的构建输出文件,确保后续构建从干净的状态开始。
    • post-clean:在清理后执行,通常用于执行清理后的操作(如恢复备份文件)。

典型使用场景

  • 项目初次构建前:避免旧版本文件干扰。
  • 构建失败后重新尝试:清除可能存在的错误产物。
  • 切换分支或环境时:确保不同环境的构建隔离。

示例命令

mvn clean          # 执行 clean 生命周期的 clean 阶段
mvn clean package  # 先清理,再执行 package 阶段

2. Default 生命周期(Build 生命周期)

作用构建项目,从源代码编译到打包、测试、安装和部署。

  • 核心阶段(部分关键阶段):
    • validate:验证项目配置(如 pom.xml 是否正确)。
    • compile:编译主源代码(src/main/java)。
    • test:运行单元测试(src/test/java)。
    • package:将编译后的代码打包(如 JAR、WAR)。
    • verify:验证打包结果是否符合质量标准。
    • install:将包安装到本地 Maven 仓库(~/.m2/repository),供其他项目使用。
    • deploy:将包部署到远程仓库(如 Nexus),供团队共享。

典型使用场景

  • 日常开发mvn compilemvn test 用于局部构建和测试。
  • 打包部署mvn packagemvn install 用于生成可分发的包。
  • 发布版本mvn deploy 将最终包推送到远程仓库。

示例命令

mvn compile        # 编译主代码
mvn test           # 编译并运行测试
mvn package        # 编译、测试并打包
mvn install        # 安装到本地仓库
mvn deploy         # 部署到远程仓库

3. Site 生命周期

作用生成项目文档和站点信息,用于项目报告和团队协作。

  • 核心阶段
    • pre-site:生成文档前的准备操作。
    • site生成项目站点文档(如 API 文档、测试报告、项目统计信息)。
    • post-site:生成文档后的处理(如自定义脚本)。
    • site-deploy将文档部署到远程服务器(如 GitHub Pages、Nexus)。

典型使用场景

  • 项目文档生成:通过 mvn site 生成 HTML 格式的 API 文档、测试覆盖率报告等。
  • 团队协作:使用 mvn site-deploy 将文档发布到团队内部服务器或公共网站。

示例命令

mvn site           # 生成项目文档
mvn site-deploy    # 将文档部署到远程服务器

总结对比

生命周期核心目的典型命令适用场景
Clean清理构建产物mvn clean重新构建前、切换环境
Default构建、测试、打包、部署mvn compile, mvn deploy日常开发、版本发布
Site生成和部署项目文档mvn site, mvn site-deploy项目文档维护、团队协作

补充说明

  • 生命周期的独立性:三种生命周期相互独立,互不干扰。例如,mvn clean 只执行 Clean 生命周期,不会影响 Default 或 Site。
  • 插件绑定:每个生命周期的阶段通常绑定特定插件(如 maven-compiler-plugin 绑定到 compile 阶段),用户可通过自定义插件扩展功能。
  • 命令组合:Maven 支持组合命令,如 mvn clean package 会依次执行 Clean 生命周期的 clean 阶段和 Default 生命周期的 package 阶段。

JVM

JVM 组件有哪些?

JVM(Java Virtual Machine)的核心组件包括以下部分:

  1. 类加载子系统(Class Loader System)

    • 作用:负责将 .class 文件加载到 JVM 中,并验证、解析和初始化类。
    • 关键流程
      • 加载:从文件系统、网络或内存中读取类的二进制数据。
      • 验证:确保类符合 JVM 规范(如字节码校验)。
      • 准备:为类变量(static 变量)分配内存并设置默认值。
      • 解析:将符号引用转换为直接引用(如方法地址)。
      • 初始化:执行类构造器 <clinit> 方法(静态代码块和静态变量赋值)。
  2. 运行时数据区(Runtime Data Areas)

    • 程序计数器(Program Counter Register)
      • 线程私有,记录当前线程执行的字节码指令地址。
    • Java 虚拟机栈(Java Virtual Machine Stacks)
      • 线程私有,存储局部变量、操作数栈、动态链接、方法返回地址等。
      • 每个方法调用会创建一个栈帧(Stack Frame)。
    • 本地方法栈(Native Method Stack)
      • 用于执行 Native 方法(如 JNI 调用)。
    • 堆(Heap)
      • 所有线程共享,存储对象实例和数组。
      • 分代管理:新生代(Young Generation)、老年代(Old Generation)、元空间(Metaspace)。
    • 方法区(Method Area)
      • 存储类的元数据(如类信息、常量池、静态变量、编译器编译后的代码缓存)。
      • 永久代(PermGen)(JDK 8 之前) vs 元空间(Metaspace)(JDK 8+)。
  3. 执行引擎(Execution Engine)

    • 作用:将字节码转换为本地机器指令执行。
    • 核心功能
      • 解释器(Interpreter):逐行解释字节码,速度快但效率低。
      • 即时编译器(JIT Compiler):将热点代码编译为本地机器码,优化性能。
      • 垃圾回收器(Garbage Collector):管理堆内存,回收无用对象。
  4. 本地方法接口(Native Interface)

    • 提供与本地库(如 C/C++)交互的接口(JNI)。
    • 用于实现 JVM 内部无法直接完成的功能(如文件 I/O、多线程调度)。

什么是逃逸分析(Escape Analysis)?

逃逸分析是 JVM 在 即时编译(JIT)阶段 的一种高级优化技术,用于判断对象的作用域范围,是否“逃逸”出当前方法或线程。

对象逃逸的三种状态
  1. 不逃逸(NoEscape):对象仅在当前方法内部使用。
    • 优化:栈上分配(Stack Allocation)、标量替换(Scalar Replacement)。
  2. 方法逃逸(ArgEscape):对象作为参数传递给其他方法。
    • 优化:同步消除(Synchronization Elimination)。
  3. 线程逃逸(GlobalEscape):对象被其他线程访问。
    • 优化:几乎无法优化。
逃逸分析的价值
  1. 栈上分配:避免堆内存分配压力,减少 GC 压力。
  2. 标量替换:将对象拆分为基本类型(如 Point x, y 拆分为 int x, int y)。
  3. 同步消除:移除不必要的锁操作(如 synchronized)。
触发条件
  • 方法被频繁调用(热点代码)。
  • 对象生命周期可准确分析。
  • JVM 运行在 Server 模式(-server)。
示例
public void process() {Point p = new Point(1, 2); // 不逃逸对象System.out.println(p.x + p.y);
}

JVM 可能将 p 栈上分配,无需堆内存分配。


对永久代(PermGen)和元空间(Metaspace)的看法

永久代(PermGen)(JDK 8 之前):
  • 特点
    • 存在于堆中,大小有限(需手动配置 -XX:MaxPermSize)。
    • 垃圾回收效率低,容易导致 OutOfMemoryError: PermGen space
  • 缺点
    • 配置复杂,内存管理不够灵活。
    • 元数据(如类信息)和堆内存耦合,难以隔离。
元空间(Metaspace)(JDK 8+):
  • 特点
    • 使用 本地内存(Native Memory),不受堆内存限制。
    • 默认无上限,可通过 -XX:MaxMetaspaceSize 限制。
  • 优势
    • 内存管理更灵活高效,减少 OOM 风险。
    • 与堆解耦,便于隔离元数据和堆内存。
    • 支持动态扩展,适应大规模类加载场景。
迁移建议
  • 推荐使用元空间:避免 PermGen 的配置复杂性和 OOM 问题。
  • 监控元空间:使用 jcmd VM.native_memoryjstat -gcmetacapacity 监控元空间占用。

JIT 是什么?

JIT(Just-In-Time Compiler) 是 JVM 的即时编译器,将热点字节码编译为本地机器码,提升执行效率。

核心功能
  1. 热点代码识别:通过采样或计数器(如 InvokeCounter)识别频繁执行的代码。
  2. 编译优化
    • 方法内联(Inlining):将小方法直接嵌入调用处。
    • 寄存器分配(Register Allocation):优化寄存器使用,减少内存访问。
    • 消除冗余代码:如常量折叠、死代码删除。
  3. 动态优化:根据运行时数据(如分支概率)调整编译策略。
JIT 分类
  • 经济 JIT(C1 编译器):快速编译,无复杂优化,适用于资源紧张环境。
  • 普通 JIT(C2 编译器):全面优化,适合性能敏感场景(如服务端应用)。
JIT 优化示例
public int sum(int a, int b) {return a + b; // 热点方法可能被内联
}

JIT 会将 sum 方法内联到调用处,减少方法调用开销。


如何监控 JVM 性能?

常用工具和命令
  1. jstat:统计 JVM 内存和 GC 情况。

    • 示例
      jstat -gc <PID> 1000 5  # 每秒打印 GC 统计信息 5 次
      jstat -gcutil <PID> 1000 5  # 查看 GC 利用率
      
  2. jcmd:查看 JVM 状态和触发诊断操作。

    • 示例
      jcmd <PID> VM.native_memory summary  # 查看堆外内存使用
      jcmd <PID> GC.class_histogram  # 查看堆内存对象分布
      
  3. jconsole/VisualVM:图形化监控内存、线程、GC 等。

  4. Arthas(阿里开源):

    • 功能
      • 实时查看线程状态(thread)。
      • 分析内存泄漏(monitor)。
      • 诊断死锁(thread -b)。
  5. NMT(Native Memory Tracking)

    • 启用
      -XX:NativeMemoryTracking=summary  # 基础模式
      -XX:NativeMemoryTracking=detail  # 详细模式
      
    • 查看
      jcmd <PID> VM.native_memory summary scale=MB
      
  6. GC 日志分析

    • 启用参数
      -Xlog:gc*:file=gc.log:time:filecount=5,filesize=10M
      
    • 分析工具:GCEasy、GCViewer、VisualVM。
监控指标
  • GC 停顿时间:控制在 MaxGCPauseMillis(如 200ms)。
  • 堆内存使用率:避免频繁 Full GC(老年代使用率 > 70%)。
  • 线程状态:检查 BLOCKEDWAITING 线程占比。

JVM 如何实现线程同步?

核心机制
  1. synchronized 关键字

    • 对象锁:对类实例加锁(synchronized(this))。
    • 类锁:对类加锁(synchronized(ClassName.class))。
    • 锁升级:偏向锁 → 轻量级锁 → 重量级锁(JDK 6+)。
  2. Lock 接口(ReentrantLock)

    • 显式锁:需手动 lock()unlock()
    • 公平锁:按请求顺序获取锁(ReentrantLock(true))。
    • 条件变量:通过 Condition 实现线程间通信(替代 wait/notify)。
  3. volatile 关键字

    • 保证可见性:写操作对其他线程立即可见。
    • 禁止指令重排序:通过内存屏障(Memory Barrier)实现。
  4. Atomic 类(CAS 原理)

    • 无锁操作:基于 CPU 原子指令(如 Compare And Swap)。
    • 典型实现AtomicIntegerAtomicReference
生产者-消费者模式示例
BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
// 生产者
new Thread(() -> {while (true) {queue.put("data");  // 阻塞直到队列未满}
}).start();
// 消费者
new Thread(() -> {while (true) {String data = queue.take();  // 阻塞直到队列非空}
}).start();

死锁检测的命令

常用命令
  1. jstack:生成线程转储(Thread Dump),分析死锁。

    • 示例
      jstack <PID> > thread_dump.txt
      
    • 输出分析
      Found one Java-level deadlock:
      "Thread-1":waiting to lock monitor 0x00007f8c0000,which is held by "Thread-0"
      "Thread-0":waiting to lock monitor 0x00007f8c0001,which is held by "Thread-1"
      
  2. Arthas

    • 命令
      thread -b  # 查找死锁
      
  3. jcmd

    • 示例
      jcmd <PID> Thread.print  # 查看线程状态
      
预防死锁
  • 按固定顺序获取锁
  • 设置超时tryLock(timeout))。
  • 减少锁粒度(如分段锁)。

主流的垃圾回收器和算法

垃圾回收算法
  1. 标记-清除(Mark-Sweep)

    • 流程:标记存活对象 → 清除无用对象。
    • 缺点:产生内存碎片,可能导致大对象分配失败。
  2. 标记-整理(Mark-Compact)

    • 流程:标记存活对象 → 整理至内存一端。
    • 优点:避免内存碎片,适合老年代。
  3. 复制(Copying)

    • 流程:将存活对象复制到另一块内存区域。
    • 典型应用:新生代的 Eden 区和 Survivor 区。
  4. 分代收集(Generational Collection)

    • 理论基础
      • 弱分代假说:大多数对象生命周期短。
      • 强分代假说:熬过多次 GC 的对象更难消亡。
    • 分代策略
      • 新生代(Young Gen):使用复制算法(Serial、ParNew)。
      • 老年代(Old Gen):使用标记-整理或标记-清除(CMS、G1)。
主流垃圾回收器
  1. Serial GC(单线程,适用于单核机器)

    • 特点:Stop-The-World,适合小型应用。
  2. Parallel Scavenge GC(多线程,吞吐优先)

    • 特点:并行回收,适合批处理任务。
  3. CMS GC(并发标记清除,低延迟)

    • 缺点:产生内存碎片,需配合 CMSInitiatingOccupancyFraction
  4. G1 GC(Garbage-First,适用于大堆内存)

    • 特点:分区回收(Region),平衡吞吐和延迟。
    • 关键参数
      -XX:+UseG1GC  # 启用 G1
      -XX:MaxGCPauseMillis=200  # 控制最大停顿时间
      -XX:G1HeapRegionSize=4M  # 区域大小
      
  5. ZGC/Shenandoah(低延迟,毫秒级停顿)

    • 特点:染色指针(Colored Pointers)或 Load Barrier 技术。
选择建议
  • 吞吐优先:Parallel Scavenge + Serial Old。
  • 低延迟:G1 或 ZGC(JDK 11+)。
  • 大堆内存:G1 或 ZGC。

JUC

你对 Executor 框架的了解

Executor 框架是 Java 并发编程的核心工具,通过解耦任务的提交与执行,提供高效、灵活的多线程解决方案。其核心接口和实现包括:

  1. Executor
    • 最基本的接口,定义 execute(Runnable command) 方法,用于执行提交的任务。
  2. ExecutorService
    • 扩展 Executor,提供更丰富的功能:
      • 提交任务(submit(Runnable/Callable))。
      • 关闭线程池(shutdown()shutdownNow())。
      • 管理任务生命周期(isShutdown()awaitTermination())。
  3. ScheduledExecutorService
    • 支持定时或周期性任务(如 schedule()scheduleAtFixedRate())。

线程池实现

  • ThreadPoolExecutor:核心线程池,支持自定义参数(核心线程数、最大线程数、任务队列等)。
  • ScheduledThreadPoolExecutor:支持定时任务的线程池。

优势

  • 资源管理:通过线程复用减少创建/销毁开销。
  • 任务调度:支持优先级、延迟、周期性任务。
  • 优雅关闭:通过 shutdown()shutdownNow() 安全终止线程池。

示例

ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> System.out.println("Task executed"));
executor.shutdown();

你对 JUC 的了解

JUC(java.util.concurrent)是 Java 并发编程的核心包,提供以下组件:

  1. 线程池(Executor 框架):管理线程生命周期,提升资源利用率。
  2. 同步工具
    • CountDownLatch:等待多个线程完成。
    • CyclicBarrier:让线程互相等待到达屏障点。
    • Semaphore:控制资源访问数量。
  3. 原子类Atomic 系列):基于 CAS 实现无锁操作(如 AtomicInteger)。
  4. 并发集合
    • ConcurrentHashMap:线程安全的哈希表。
    • CopyOnWriteArrayList:写时复制的列表。
  5. 阻塞队列
    • ArrayBlockingQueue:有界队列。
    • LinkedBlockingQueue:无界或有界队列。
    • SynchronousQueue:无缓冲队列。

核心目标

  • 解决并发场景下的线程安全、资源竞争、死锁等问题。
  • 提供高性能、可扩展的并发工具。

谈谈 Callable 和 Future 用法

  1. Callable
    • 返回结果的任务接口,定义 call() 方法(有返回值)。
    • Runnable 的区别:支持返回值和抛出异常。
  2. Future
    • 表示异步计算的结果,提供以下方法:
      • get():获取任务结果(阻塞直到完成)。
      • cancel():取消任务。
      • isDone():判断任务是否完成。

使用示例

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(() -> {return 42;
});
System.out.println(future.get()); // 输出 42
executor.shutdown();

CountDownLatch 应用举例

作用:让一个或多个线程等待其他线程完成操作。
典型场景:主线程等待多个子线程完成初始化。

示例

CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {new Thread(() -> {// 模拟子线程工作latch.countDown();}).start();
}
latch.await(); // 主线程等待
System.out.println("All threads completed");

CyclicBarrier 应用举例

作用:让一组线程互相等待,直到所有线程到达屏障点。
典型场景:多线程协同计算(如赛跑选手同时起跑)。

示例

CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All arrived!"));
for (int i = 0; i < 3; i++) {new Thread(() -> {try {barrier.await(); // 等待其他线程} catch (Exception e) {}}).start();
}

Atomic 常见使用

核心原理:基于 CAS(Compare and Swap) 实现无锁操作。
常用类

  • AtomicInteger:原子整数操作。
  • AtomicReference:原子引用操作。
  • AtomicLong:原子长整型操作。

应用场景

  • 计数器:线程安全的递增/递减。
  • 状态标志:无锁状态更新(如 AtomicBoolean)。

示例

AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // 原子递增

阻塞队列有哪些实现?你了解 AQS 吗?谈一谈

阻塞队列实现
  1. ArrayBlockingQueue:有界队列,基于数组。
  2. LinkedBlockingQueue:无界或有界队列,基于链表。
  3. PriorityBlockingQueue:支持优先级排序的无界队列。
  4. SynchronousQueue:无缓冲队列(直接传递)。
  5. DelayQueue:元素需延迟到期后才能取出。
AQS(AbstractQueuedSynchronizer)

核心作用:为同步组件(如 ReentrantLockSemaphore)提供基础实现。
关键特性

  • CLH 队列:维护等待线程的队列。
  • 状态管理:通过 state 变量控制资源状态(如锁的持有)。
  • 支持模式
    • 独占模式(如 ReentrantLock):仅允许一个线程持有锁。
    • 共享模式(如 CountDownLatch):允许多个线程同时访问。

实现原理

  • 线程尝试获取资源时,若失败则进入等待队列。
  • 释放资源时,唤醒队列中的下一个线程。

ConcurrentHashMap 和 Hashtable 区别

特性ConcurrentHashMapHashtable
线程安全机制分段锁(JDK 8 前)或 CAS+synchronized(JDK 8+)全局锁(synchronized 方法)
性能高(并发读写效率高)低(所有操作都加锁)
迭代器弱一致性(不会抛异常)强一致性(可能抛 ConcurrentModificationException
是否支持 null不支持支持
扩容机制动态扩容(并发进行)需要手动扩容

适用场景

  • ConcurrentHashMap:高并发读写场景(如缓存)。
  • Hashtable:遗留代码或低并发场景。
http://www.xdnf.cn/news/6201.html

相关文章:

  • 数据清洗ETL
  • 【Python 算法零基础 2.模拟 ④ 基于矩阵】
  • 【starrocks】StarRocks 常见 HTTP 操作与导入错误排查指南
  • 数值积分知识
  • MK米客方德SD NAND:无人机存储的高效解决方案
  • Qwen-3 模型的应用及实际用例
  • 面向具身智能的视觉-语言-动作模型(VLA)综述
  • 大数据开发 hadoop集群 3.Hadoop运行环境搭建
  • 【Linux】第十六章 分析和存储日志
  • voip--初始化libosip2库
  • 首个专业AI设计Agent发布-Lovart
  • nvrtc环境依赖
  • C++类和对象之相关特性
  • 养猪场巡检机器人的设计与应用研究
  • Python环境管理工具深度指南:pip、Poetry、uv、Conda
  • Vue3学习(组合式API——Watch侦听器详解)
  • Large-Scale Language Models: In-Depth Principles and Pioneering Innovations
  • 输入一个正整数,将其各位数字倒序输出(如输入123,输出321)
  • 基于GPUGEEK 平台进行深度学习
  • 昆士兰科技大学无人机自主导航探索新框架!UAVNav:GNSS拒止与视觉受限环境中的无人机导航与目标检测
  • [学习] RTKLib详解:rtcm2.c、rtcm3.c、rtcm3e与rtcmn.c
  • 阿里云Docker镜像加速配置指南
  • Nginx配置与应用案例详解
  • 深圳无人机展览即将开始,无人机舵机为什么选择伟创动力
  • Single image dehazing论文阅读
  • 鸿蒙OSUniApp 实现的语音输入与语音识别功能#三方框架 #Uniapp
  • Python----神经网络(《Searching for MobileNetV3》论文概括和MobileNetV3网络)
  • Qt原型模式实现与应用
  • auto.js面试题及答案
  • python如何合并excel单元格