一、上下文切换深度解析
1. 切换过程拆解
2. 性能影响关键点
- 直接开销:
- 寄存器保存/恢复:约1000-3000时钟周期
- TLB缓存失效:导致内存访问延迟增加
- 间接开销:
- CPU缓存命中率下降(新线程数据未缓存)
- 调度器计算消耗(如CFS调度器的红黑树调整)
3. 优化策略
1. 避免过度创建线程(使用线程池)
2. 减小临界区范围(同步代码块最小化)
3. 使用无锁数据结构(如ConcurrentHashMap)
二、线程创建方式对比
1. 无返回值实现
方式 |
示例代码 |
优缺点 |
继承Thread |
class MyThread extends Thread |
简单但Java单继承限制 |
实现Runnable |
new Thread(() -> {}).start() |
推荐方案,灵活组合 |
2. 带返回值实现
Callable<Integer> task = () -> {
TimeUnit.SECONDS.sleep(1);
return 42;
};
FutureTask<Integer> future = new FutureTask<>(task);
new Thread(future).start();
System.out.println(future.get());
三、线程中断机制详解
1. 中断流程
2. 正确中断实践
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
四、volatile与锁的对比
1. volatile适用场景
2. 锁的选择策略
锁类型 |
特点 |
适用场景 |
synchronized |
JVM内置,自动释放 |
简单同步需求 |
ReentrantLock |
可中断、公平锁、条件变量 |
复杂同步控制 |
StampedLock |
乐观读锁 |
读多写少的高性能场景 |
五、CompletableFuture进阶
1. 核心方法速查
方法 |
作用 |
异步示例 |
supplyAsync() |
带返回值的异步任务 |
supplyAsync(() -> "result") |
thenApply() |
结果转换 |
.thenApply(s -> s.length()) |
thenCombine() |
合并两个任务结果 |
future1.thenCombine(future2, (a,b) -> a+b) |
exceptionally() |
异常处理 |
.exceptionally(ex -> "fallback") |
2. 超时控制最佳实践
CompletableFuture.supplyAsync(() -> {
return fetchData();
}).get(2, TimeUnit.SECONDS);
六、生产环境问题排查
1. 线程状态诊断命令
jstack <pid> | grep -A 1 "java.lang.Thread.State"
jcmd <pid> Thread.print
2. 常见死锁模式
Thread1: 锁定A后尝试获取B
Thread2: 锁定B后尝试获取A
通过jstack
输出的Found one Java-level deadlock
可快速定位。