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 秒后)
回调收到: 数据

五、总结

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

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

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

相关推荐
苏supper5 分钟前
记一次Nacos鉴权报错unknown user,403排查|SecurityProxy源码,fastjson2扩展包缺失
java·后端
\光辉岁月/7 分钟前
6.mybatisplus学习-BaseMapper、Service、常用注解
java·mybatis·mybatisplus
微信开发api8 分钟前
基于WTAPI构建社群运营平台:自动拉群与会话承接链路设计
java·大数据·网络·数据库·微信·自动化
凉茶钱11 分钟前
【C++】动态内存管理完整解析:从内存划分到 new delete 底层原理
c语言·开发语言·c++·内存管理·动态内存
小七在进步14 分钟前
类和对象(五)
java·开发语言·算法
Rebecca_aLi16 分钟前
码匠教育:零基础学 Python,标识符到循环全套基础语法解析
开发语言·python·正则表达式
IvanCodes23 分钟前
Python 正则表达式(十四):文本匹配、查找与替换
开发语言·python·正则表达式
夜雪一千24 分钟前
Python URL编码踩坑:单层编码、双重编码实战解析
开发语言·python
孙启超28 分钟前
【AI开发之Rust】第 21 课:双端集成与出包 —— Android(.so→AAR)与 iOS(xcframework)
开发语言·后端·rust
Brilliantwxx38 分钟前
【STM32】 __weak 弱引用、中断标志位、异常处理与 HAL_Delay 优先级
开发语言·stm32·单片机·嵌入式硬件