Java中同步和异步的区别,以及阻塞和非阻塞的区别
一、同步 vs 异步
同步(Synchronous)
- 调用者主动等待结果
- 结果没回来,调用者不能做下一件事(必须排队)
异步(Asynchronous)
- 调用者不等结果
- 把任务交给别人执行,自己继续干别的
📌 同步/异步的本质:看调用者是否“等待结果”。
二、阻塞 vs 非阻塞
阻塞(Blocking)
- 线程停在这里,啥也干不了
- 线程被“卡住”等待资源或事件
非阻塞(Non-blocking)
- 线程不会被卡住
- 如果得不到结果会马上返回,不会停下来等
📌 阻塞/非阻塞本质:看线程有没有被卡住。
✔ 同步 vs 异步:“调用方要不要等结果”
✔ 阻塞 vs 非阻塞:线程在等的时候是否被卡住
三、四种组合
| 组合 | 是否等待结果(同步/异步) | 线程是否被卡住(阻塞/非阻塞) |
|---|---|---|
| 同步阻塞 | 等 | 卡住 |
| 同步非阻塞 | 等 | 不卡住(轮询) |
| 异步阻塞 | 不等 | 卡住(几乎不用) |
| 异步非阻塞 | 不等 | 不卡住(最优秀) |
四、使用代码演示每一种情况
1. 同步阻塞(Synchronous Blocking)
📌 最常见、最容易理解
调用 getData(),要等结果返回才继续往下执行。
public String getData() {// 假设这里访问网络,需要 3 秒Thread.sleep(3000);return "数据";
}public void demo() {System.out.println("开始");String result = getData(); // 同步 + 阻塞:卡住等结果System.out.println("结果: " + result);System.out.println("结束");
}
执行顺序:
开始
(线程卡住 3 秒)
结果: 数据
结束
2. 同步非阻塞(Synchronous Non-blocking)
📌 调用者会持续检查结果,但线程不被卡住
常见于"轮询"。
private volatile String result = null;public void request() {// 模拟后台线程处理new Thread(() -> {try {Thread.sleep(3000);result = "后台完成";} catch (Exception e) {}}).start();
}public void demo() {System.out.println("开始");request(); // 发出任务// 同步非阻塞:不被卡住,但必须自己循环检查(轮询)while (result == null) {System.out.println("我在等,但我没被卡住...");try { Thread.sleep(200); } catch (Exception e) {}}System.out.println("结果: " + result);System.out.println("结束");
}
3. 异步阻塞(Asynchronous Blocking)
📌 这种情况很少用,但理论上存在
调用异步任务,但最终仍然调用 get() 阻塞等待。
public void demo() throws Exception {ExecutorService executor = Executors.newSingleThreadExecutor();Future<String> future = executor.submit(() -> {Thread.sleep(3000);return "数据";});System.out.println("开始");// 异步提交任务// 但是这里用 get() 阻塞住了String result = future.get(); // 异步 + 阻塞System.out.println("收到: " + result);executor.shutdown();
}
4. 异步非阻塞(Asynchronous Non-blocking)
📌 最优秀的模式:
- 调用不会等待
- 线程不会被卡住
- 结果通过回调、事件、消息通知回来
public void asyncGetData(Consumer<String> callback) {new Thread(() -> {try {Thread.sleep(3000);callback.accept("数据");} catch (Exception e) {}}).start();
}public void demo() {System.out.println("开始");// 异步非阻塞:不用等,不阻塞线程asyncGetData(result -> {System.out.println("回调收到: " + result);});System.out.println("我可以继续干别的事情");
}
输出顺序:
开始
我可以继续干别的事情
(3 秒后)
回调收到: 数据
五、总结
| 概念 | 定义 |
|---|---|
| 同步 | 调用者等待结果 |
| 异步 | 调用者不等待结果 |
| 阻塞 | 当前线程停住、不能干其他事 |
| 非阻塞 | 当前线程不会停住 |
📌 同步/异步 = 逻辑上的等待
📌 阻塞/非阻塞 = 线程状态是否被卡住
