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

五、总结

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

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

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

相关推荐
学长毕设23 分钟前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
码途行者1 小时前
网站的SQL 注入:从攻击原理到防御措施
开发语言·sql·php
SimonKing1 小时前
震惊:怎么回事,opencode一轮对话耗尽免费额度
java·后端·程序员
装不满的克莱因瓶1 小时前
【SpringAI Alibaba】ReactAgent响应SSE实时流式传输案例实战
java·人工智能·ai·sse·springai
杨凯凡1 小时前
Spring Boot 文件上传怎么做才安全?流式落盘、路径校验与数据库一致性实战
java·spring boot·文件上传·后端安全·数据库一致性
旖旎夜光1 小时前
【C++ 基础入门】C++ 多态(中):虚函数表、多态原理与动静绑定
开发语言·c++·笔记·学习
这个昵称不容易1 小时前
旅游管理系统的设计与实现(SpringBoot + MySQL + Vue 前后端分离)
java·springboot·毕设
Rain的Java大神之路1 小时前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
你看我名字1 小时前
产品参数昨天还对,今天已过期:数眼智能与大模型应用如何做资料版本校验
开发语言·架构
老秦包你会2 小时前
计算机网络第二课 ----Socket(套接字)编程预备
开发语言·计算机网络·php