Java中同步和异步的区别,以及阻塞和非阻塞的区别

一、同步 vs 异步

同步(Synchronous)

  • 调用者主动等待结果
  • 结果没回来,调用者不能做下一件事(必须排队)

异步(Asynchronous)

  • 调用者不等结果
  • 把任务交给别人执行,自己继续干别的

📌 同步/异步的本质:看调用者是否"等待结果"。


二、阻塞 vs 非阻塞

阻塞(Blocking)

  • 线程停在这里,啥也干不了
  • 线程被"卡住"等待资源或事件

非阻塞(Non-blocking)

  • 线程不会被卡住
  • 如果得不到结果会马上返回,不会停下来等

📌 阻塞/非阻塞本质:看线程有没有被卡住。


✔ 同步 vs 异步:"调用方要不要等结果"

✔ 阻塞 vs 非阻塞:线程在等的时候是否被卡住

三、四种组合

组合 是否等待结果(同步/异步) 线程是否被卡住(阻塞/非阻塞)
同步阻塞 卡住
同步非阻塞 不卡住(轮询)
异步阻塞 不等 卡住(几乎不用)
异步非阻塞 不等 不卡住(最优秀)

四、使用代码演示每一种情况


1. 同步阻塞(Synchronous Blocking)

📌 最常见、最容易理解
调用 getData(),要等结果返回才继续往下执行。

java 复制代码
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)

📌 调用者会持续检查结果,但线程不被卡住

常见于"轮询"。

java 复制代码
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() 阻塞等待。

java 复制代码
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)

📌 最优秀的模式

  • 调用不会等待
  • 线程不会被卡住
  • 结果通过回调、事件、消息通知回来
java 复制代码
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 秒后)
回调收到: 数据

五、总结

概念 定义
同步 调用者等待结果
异步 调用者不等待结果
阻塞 当前线程停住、不能干其他事
非阻塞 当前线程不会停住

📌 同步/异步 = 逻辑上的等待

📌 阻塞/非阻塞 = 线程状态是否被卡住

相关推荐
AGANCUDA9 小时前
qt使用osg显示pcd点云的例子
开发语言·qt
2301_815686459 小时前
extern
java·开发语言
q***56389 小时前
Java进阶-SPI机制
java·开发语言
曾经的三心草10 小时前
基于正倒排索引的Java文档搜索引擎2-实现Index类
java·python·搜索引擎
g***B73810 小时前
Rust在网络中的Tokio
开发语言·网络·rust
寻找华年的锦瑟10 小时前
Qt-侧边栏布局
开发语言·qt
1560820721910 小时前
QT的ComboBox使用QToolTip显示提示信息
开发语言
tyler-泰勒10 小时前
QT:基础概念操作
开发语言·qt
9***P33410 小时前
Rust在网络中的Rocket
开发语言·后端·rust