1. CompletableFuture组合异步任务的异常处理
异常处理方法
-
exceptionally:- 处理链中任意阶段的异常,返回默认值。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) throw new RuntimeException("Error"); return "Success"; }).exceptionally(ex -> { System.err.println("Exception: " + ex.getMessage()); return "Default"; }); -
handle:- 同时处理正常结果和异常,支持恢复逻辑。
future.handle((result, ex) -> { if (ex != null) { return "Recovered"; } return result; }); -
whenComplete:- 执行清理操作,但不修改结果。
future.whenComplete((res, ex) -> { if (ex != null) { System.err.println("Task failed: " + ex.getMessage()); } }); -
多任务异常处理:
- 使用
allOf或anyOf统一处理多个任务异常。
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2); allFutures.exceptionally(ex -> { System.err.println("All tasks failed: " + ex.getMessage()); return null; }); - 使用
2. CompletableFuture异步任务超时处理
解决方案
-
get(timeout, TimeUnit):- 直接设置超时时间,超时后抛出异常。
try { String result = future.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { future.cancel(true); // 取消任务 } -
自定义超时逻辑:
- 结合
CompletableFuture和ScheduledExecutorService。
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); CompletableFuture<String> timeoutFuture = new CompletableFuture<>(); scheduler.schedule(() -> timeoutFuture.completeExceptionally(new TimeoutException()), 5, TimeUnit.SECONDS); CompletableFuture.anyOf(future, timeoutFuture).thenApply(result -> { if (timeoutFuture.isDone()) { System.err.println("Task timed out"); } return result; }); - 结合
3. JMM(Java内存模型)
- 核心作用:
- 定义线程如何与主内存交互,确保可见性、原子性和有序性。
- 关键规则:
- happens-before:定义操作顺序,如
synchronized、volatile写-读。 - 可见性:
volatile确保变量修改对其他线程立即可见。 - 原子性:
synchronized和AtomicXXX类保证复合操作的原子性。 - 有序性:禁止指令重排序(通过内存屏障)。
- happens-before:定义操作顺序,如
4. JVM内存模型
内存区域划分
- 堆(Heap):
- 存放对象实例,分为新生代(Young)和老年代(Old)。
- 栈(Stack):
- 存储局部变量和方法调用。
- 方法区(Metaspace):
- 存储类元数据(如类定义、常量池)。
- 程序计数器:
- 记录当前线程执行的字节码地址。
5. 方法重载 vs 方法重写
| 特性 | 方法重载(Overload) | 方法重写(Override) |
|---|---|---|
| 定义位置 | 同一个类或子类 | 子类覆盖父类方法 |
| 方法签名 | 方法名相同,参数列表不同 | 方法名、参数列表、返回类型相同 |
| 访问权限 | 可以更严格 | 不能更严格(如父类是 protected,子类不能是 private) |
| 目的 | 提供多种调用方式 | 实现多态 |
6. Redis持久化机制
RDB(快照)
- 优点:
- 文件体积小,恢复速度快。
- 不阻塞主线程(通过子进程生成快照)。
- 缺点:
- 数据可能丢失(最后一次快照后未持久化的数据)。
- 不适合高频率写入场景。
AOF(Append-Only File)
- 优点:
- 数据安全性高(每条写命令记录)。
- 支持重写压缩(
BGREWRITEAOF)。
- 缺点:
- 文件体积大,恢复速度慢。
- 频繁写入可能影响性能。
部署方式
- 单机部署:适用于小型应用,简单易用。
- 主从复制:主节点写,从节点读,提升读性能。
- 集群部署:分片存储,高可用,支持水平扩展。
7. 查询全表性能差的优化
-
添加索引:
- 在查询条件字段(如手机号)上创建索引。
CREATE INDEX idx_phone ON users(phone); -
分区表:
- 按手机号范围或哈希分区,减少扫描数据量。
CREATE TABLE users_partitioned ( id INT, phone VARCHAR(20) ) PARTITION BY RANGE (id); -
缓存:
- 使用Redis缓存高频查询结果(如手机号对应的用户ID)。
-
优化查询语句:
- 避免
SELECT *,只查询必要字段。
- 避免
8. 撤销已提交到Git远端的内容
步骤
-
本地回滚:
git revert <commit-hash> # 创建新提交撤销旧提交 -
推送到远端:
git push origin <branch-name> -
强制推送(慎用):
- 若已强制推送过历史提交,需使用
--force:
git push origin <branch-name> --force - 若已强制推送过历史提交,需使用
9. Maven依赖冲突解决
方法
-
显式声明依赖版本:
<dependencyManagement> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>my-component</artifactId> <version>1.0.0</version> </dependency> </dependencies> </dependencyManagement> -
使用
mvn dependency:tree:- 查看依赖树,定位冲突的依赖路径。
-
排除冲突依赖:
<dependency> <groupId>com.example</groupId> <artifactId>my-lib</artifactId> <exclusions> <exclusion> <groupId>com.conflict</groupId> <artifactId>bad-lib</artifactId> </exclusion> </exclusions> </dependency>
10. Linux常用命令
awk 命令
- 用途:文本处理,按行/列提取数据。
# 提取日志中错误级别为ERROR的行 awk '/ERROR/ {print $0}' /var/log/app.log
查看日志命令
-
tail -f:tail -f /var/log/app.log -
grep+tail:tail -n 100 /var/log/app.log | grep "ERROR" -
less分页查看:less /var/log/app.log
11. Elasticsearch倒排索引原理
- 核心思想:
- 将文档拆分为词项(term),建立词项到文档的映射。
- 示例:
文档1: "Java is great" 文档2: "Python is awesome" 倒排索引: Java -> [文档1] is -> [文档1, 文档2] great -> [文档1] Python -> [文档2] awesome -> [文档2]
12. 单点登录(SSO)
- 实现方式:
- OAuth2:通过第三方认证服务(如Keycloak)颁发令牌。
- JWT:用户登录后生成加密令牌,跨域传递。
- Session共享:使用Redis存储会话,共享Session ID。
13. 接口 vs 抽象类
| 特性 | 接口 | 抽象类 |
|---|---|---|
| 方法实现 | 默认方法、静态方法可有实现 | 可有抽象方法和具体方法 |
| 构造函数 | 无 | 有 |
| 继承 | 多实现 | 单继承 |
| 访问修饰符 | 方法默认 public | 可定义 protected 等 |
14. Java泛型
理解
- 作用:编译时类型检查,避免类型转换错误。
- 类型擦除:运行时泛型信息被擦除(如
List<String>变为List)。
底层实现
- 桥接方法:解决方法重写的类型擦除问题。
class Box<T> { public T get() { ... } } // 编译后生成桥接方法 public Object get() { return get(); }
15. JVM垃圾回收机制
新生代 vs 老年代设计
- 新生代:
- 标记-复制算法:减少碎片(如 Eden + Survivor 区)。
- 老年代:
- 标记-整理算法:避免碎片化(如 CMS、G1)。
减少内存碎片的机制
- 标记-整理算法:移动存活对象到连续内存。
- 分区回收:G1 将堆划分为 Region,按需回收。
16. Full GC触发条件
- 老年代空间不足。
- 元空间(Metaspace)不足。
- System.gc() 调用。
- 直接内存不足(如
ByteBuffer.allocateDirect())。
17. 排查Full GC原因
- 分析GC日志:
jstat -gcutil <pid> 1000 10 - 使用
jmap生成堆转储:jmap -dump:format=b,file=heap.bin <pid> - 工具分析:MAT(Memory Analyzer)定位内存泄漏。
18. 不适合建索引的字段
- 低基数字段:如性别(男/女)。
- 频繁更新的字段:索引维护开销大。
- 查询条件不常用的字段:索引利用率低。
19. 初始化账户服务使用消息队列的原因
- 解耦:账户服务与下游系统(如短信、邮件)解耦。
- 异步处理:提高响应速度,避免同步等待。
- 削峰填谷:应对流量高峰,防止系统崩溃。
20. 跨域Cookie共享
- 解决方案:
- 共享域名:使用
.aliyun.com作为公共域名。 - OAuth2 Token:通过认证服务颁发跨域令牌(如 JWT)。
- 代理服务器:通过 Nginx 合并域名请求。
- 共享域名:使用
21. MCP协议
- 可能指:Microservices Communication Protocol(微服务通信协议),但需具体上下文确认。
22. FunctionCall vs MCP
- FunctionCall:普通函数调用。
- MCP:假设为特定通信协议,需明确其定义。
23. Integer转int注意事项
- 自动拆箱:
Integer为null时会抛出NullPointerException。Integer a = null; int b = a; // 抛出 NullPointerException - 建议:使用
Objects.requireNonNull()或if (a != null)检查。
1. TransmittableThreadLocal 如何在子线程获取
- 核心流程:
- 捕获(Capture):父线程提交任务前,通过
Transmitter.capture()捕获所有TransmittableThreadLocal的值。 - 任务包装:使用
TtlRunnable.get(task)或TtlCallable.get(callable)包装任务,确保子线程执行时能恢复数据。 - 重放(Replay):子线程执行任务时,通过
Transmitter.replay(captured)将父线程的值复制到子线程的TransmittableThreadLocal中。 - 清理(Restore):任务完成后,通过
Transmitter.restore(backup)恢复子线程的原始状态,避免污染。
- 捕获(Capture):父线程提交任务前,通过
- 代码示例:
TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>(); threadLocal.set("Parent Value"); Runnable task = () -> { System.out.println("Child Thread Value: " + threadLocal.get()); }; // 包装任务以支持线程间传递 Runnable ttlTask = TtlRunnable.get(task); new Thread(ttlTask).start();
2. Java中的锁分类
| 锁类型 | 重入性 | 互斥性 | 公平性 | 适用场景 |
|---|---|---|---|---|
| synchronized | ✅ | 独占 | 非公平 | 简单同步,低并发场景 |
| ReentrantLock | ✅ | 独占 | 公平/非公平 | 替代 synchronized,灵活控制 |
| ReadWriteLock | ✅ | 写独占/读共享 | 公平/非公平 | 读多写少的场景 |
| StampedLock | ❌ | 写独占/读共享 | 非公平 | 高性能读多写少,需谨慎使用 |
| 分布式锁 | ❌(可扩展) | 独占 | 非公平 | 跨节点资源互斥(如 Redis) |
3. Redisson vs setnx 实现分布式锁的优势
| 特性 | Redisson | setnx 命令 |
|---|---|---|
| 自动续期 | ✅(通过看门狗机制自动延长锁过期时间) | ❌(需手动续期) |
| 异常处理 | ✅(自动释放锁,避免死锁) | ❌(需手动处理网络异常) |
| API 简化 | ✅(提供高阶 API,如 RLock) | ❌(需手动编写 Lua 脚本) |
| 性能优化 | ✅(减少网络延迟,支持批量操作) | ❌(单命令操作) |
| 可重入性 | ✅(支持同一线程多次加锁) | ❌(需自行管理) |
4. Redis 热 Key 问题
- 定义:访问频率极高的 Key,导致 Redis 单点压力集中。
- 影响:
- CPU 负载过高。
- 网络流量激增。
- 数据库雪崩风险(缓存失效后请求穿透到 DB)。
- 解决方法:
- 缓存预热:提前加载热点 Key。
- 数据分片:将热点 Key 分散到多个 Redis 实例。
- 本地缓存:使用
Caffeine等本地缓存兜底。 - 限流降级:对高频请求进行限流。
- 异步更新:通过队列异步更新缓存。
5. G1 vs ZGC
| 特性 | G1 | ZGC |
|---|---|---|
| 目标 | 可预测的 STW 时间(<1 秒) | 极低延迟(<10ms) |
| 堆大小 | 适合 10GB~几十 GB | 适合 TB 级别 |
| 内存布局 | 划分为 Region(Eden/Survivor/Old/Humongous) | 划分为 Region(大小固定为 2MB/32MB) |
| 回收算法 | 标记-整理(减少碎片) | 染色指针(无需移动对象) |
| 适用场景 | 大内存应用,平衡延迟和吞吐量 | 超低延迟场景(如金融交易系统) |
| 配置复杂度 | 较低 | 较高 |
6. 用户超时后前端处理
- 前端逻辑:
const tokenExpirationTime = 3600000; // 1小时 let lastActionTime = Date.now(); // 每分钟检查一次 setInterval(() => { const currentTime = Date.now(); if (currentTime - lastActionTime >= tokenExpirationTime) { alert("会话已超时,请重新登录!"); window.location.href = "/login"; } }, 60000); // 用户操作时更新时间 document.addEventListener("mousemove", () => { lastActionTime = Date.now(); });
7. 监控超时请求
- 实现步骤:
- 数据收集:记录每次请求的响应时间。
- 聚合分析:按时间窗口统计平均响应时间或超时率。
- 趋势检测:使用滑动窗口或指数加权移动平均(EWMA)检测异常。
- 阈值触发:当超时率连续超过阈值(如 800ms),触发告警或切换备用服务。
- 示例工具:Prometheus + Grafana 实时监控。
8. Zipkin 链路追踪
- 原理:通过 Sleuth 生成唯一 Trace ID 和 Span ID,记录请求的调用链。
- 配置步骤:
- 引入依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> - 配置 Zipkin 地址:
spring: zipkin: base-url: http://zipkin-server:9411 sampler: probability: 1.0 - 启动后访问:
http://localhost:9411查看链路详情。
- 引入依赖:
9. 日志框架选择与实现
| 框架 | 同步 vs 异步 | 底层实现 | 适用场景 |
|---|---|---|---|
| Log4j | 同步/异步 | 使用 AsyncAppender 实现异步 | 高性能要求 |
| Logback | 同步/异步 | 内置异步支持(AsyncAppender) | 简单配置,灵活扩展 |
| SLF4J | 依赖具体实现 | 门面模式,不直接处理日志写入 | 解耦业务代码与日志框架 |
- 异步日志优势:
- 减少主线程阻塞。
- 提升吞吐量(适用于高并发场景)。
- 注意事项:
- 需确保日志顺序(使用队列保证顺序性)。
- 避免日志丢失(使用可靠队列,如 Kafka)。
2035

被折叠的 条评论
为什么被折叠?



