同步 和 阻塞 听起来相似,但其实是两个不同的概念,可以组合出现。
🌟 同步 vs 阻塞的区别
| 特性 | 同步 | 阻塞 |
|---|---|---|
| 定义 | 调用方等待方法执行完成 | 线程被强制暂停等待资源 |
| 等待方式 | 必须等结果才能继续 | 没有资源,线程被挂起 |
| 线程状态 | 活跃(继续检查任务状态) | 非活跃(等待资源释放) |
| 例子 | API调用后等结果返回 | Thread.sleep() 或 read() |
| 是否可组合 | ✅ 可以阻塞或非阻塞 | ✅ 可以同步或异步 |
📖 举例理解
🎯 同步阻塞(等任务完成且线程被挂起)
public void syncBlocking() {
System.out.println("开始任务");
try {
Thread.sleep(3000); // 阻塞3秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务完成");
}
- 同步:主线程必须等
sleep()执行完才能继续 - 阻塞:
Thread.sleep会让线程挂起3秒
🎯 同步非阻塞(等任务完成但不挂起线程)
public void syncNonBlocking() {
System.out.println("开始任务");
while (System.currentTimeMillis() % 3 != 0) {
// 主动轮询资源,不挂起
}
System.out.println("任务完成");
}
- 同步:主线程仍然等任务完成
- 非阻塞:没有挂起,而是主动轮询检查
🎯 异步阻塞(不等任务完成但任务线程阻塞)
public void asyncBlocking() {
new Thread(() -> {
try {
Thread.sleep(3000); // 阻塞3秒
System.out.println("异步任务完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
System.out.println("主线程继续执行");
}
- 异步:主线程不等子任务完成
- 阻塞:子线程
sleep()挂起了3秒
🎯 异步非阻塞(不等任务完成且不挂起线程)
public void asyncNonBlocking() {
new Thread(() -> {
System.out.println("异步任务开始");
for (int i = 0; i < 5; i++) { // 模拟非阻塞轮询
System.out.println("处理中...");
}
System.out.println("异步任务完成");
}).start();
System.out.println("主线程继续执行");
}
- 异步:主线程继续执行,不等待子任务完成
- 非阻塞:子线程未挂起,而是持续处理任务
✅ 总结要点
- 同步:等任务完成再继续
- 异步:不等任务完成直接继续
- 阻塞:线程被强制暂停
- 非阻塞:线程保持活跃,主动轮询
常见组合:
- 同步阻塞:常规 API 调用
- 同步非阻塞:轮询等待
- 异步阻塞:子线程阻塞
- 异步非阻塞:事件驱动 (如 WebFlux)