简述CompletableFuture异步任务编排

前言

在之前的项目开发中,都没怎么使用过CompletableFuture的功能,只听说过和异步编程有关。为了能够在将来有需要的时候用得上,这两天花了点时间学习了一下,并简单地总结一下如何使用CompletableFuture完成异步任务编排。

先创建一个自定义的线程池,后续所有代码都会使用到:

  private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(3, 5, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadFactory() {
    private final AtomicInteger THREAD_NUM = new AtomicInteger(1);
​
    @Override
    public Thread newThread(Runnable r) {
      Thread t = new Thread(r);
//      设置为守护线程,main线程结束就跟着一起结束,否则main函数结束jvm还在
      t.setDaemon(true);
      t.setName("completable-future-test-Thread-" + THREAD_NUM.incrementAndGet());
      return t;
    }
  }, new ThreadPoolExecutor.AbortPolicy());
复制代码

同步串行

同步串行代表任务1、任务2、任务3按时间先后顺序执行,并且都是同一个线程来执行。

示例代码如下:

CompletableFuture
        .supplyAsync(
            () -> {
              Thread currentThread = Thread.currentThread();
              String ThreadName = currentThread.getName();
              String taskName = "task1";
              System.out.println(ThreadName + "开始执行任务:" + taskName);
              System.out.println("正在执行任务" + taskName);
              System.out.println(taskName + "执行结束");
              return taskName;
            }, THREAD_POOL_EXECUTOR)
        .thenApply(
            (task1Result) -> {
              Thread currentThread = Thread.currentThread();
              String ThreadName = currentThread.getName();
              String taskName = "task2";
              System.out.println(ThreadName + "开始执行任务:" + taskName);
              System.out.println("正在执行任务" + taskName);
              System.out.println("拿到上一个任务的返回值:" + task1Result);
              System.out.println(taskName + "执行结束");
              return taskName;
            })
        .thenAccept(
             (task2Result) -> {
             Thread currentThread = Thread.currentThread();
             String ThreadName = currentThread.getName();
             String taskName = "task3";
             System.out.println(ThreadName + "开始执行任务:" + taskName);
             System.out.println("正在执行任务" + taskName);
             System.out.println("拿到上一个任务的返回值:" + task2Result);
             System.out.println(taskName + "执行结束");
           });
复制代码

执行结果:

completable-future-test-Thread-2开始执行任务:task1
正在执行任务task1
task1执行结束
completable-future-test-Thread-2开始执行任务:task2
正在执行任务task2
拿到上一个任务的返回值:task1
task2执行结束
completable-future-test-Thread-2开始执行任务:task3
正在执行任务task3
拿到上一个任务的返回值:task2
task3执行结束
复制代码

1.入口函数supplyAsync()代表一个异步的有返回值的函数,之所以异步,是与主线程区别,从线程池中的拿一个线程来执行。

2.thenApply()thenAccept()没有Async,意味着是和前面的任务共用一个线程,从执行结果上我们也可以看到线程名称相同。

3.thenApply()需要接收上一个任务的返回值,并且自己也要有返回值。

4.thenAccept()需要接收上一个任务的返回值,但是它不需要返回值。

异步串行

异步串行代表任务1、任务2、任务3按时间先后顺序执行,并由不同的线程来执行。

示例代码如下:

    CompletableFuture
        // 有返回值
        .supplyAsync(
            () -> {
              Thread currentThread = Thread.currentThread();
              String ThreadName = currentThread.getName();
              String taskName = "task1";
              System.out.println(ThreadName + "开始执行任务:" + taskName);
              System.out.println("正在执行任务" + taskName);
              System.out.println(taskName + "执行结束");
              return taskName;
            }, THREAD_POOL_EXECUTOR)
        // 需要上一个任务的返回值,并且自身有返回值
        .thenApplyAsync(
            (task1Result) -> {
              Thread currentThread = Thread.currentThread();
              String ThreadName = currentThread.getName();
              String taskName = "task2";
              System.out.println(ThreadName + "开始执行任务:" + taskName);
              System.out.println("正在执行任务" + taskName);
              System.out.println("拿到上一个任务的返回值:" + task1Result);
              System.out.println(taskName + "执行结束");
              return taskName;
            }, THREAD_POOL_EXECUTOR)
        // 不需要上一个任务的返回值,自身也没有返回值
        .thenRunAsync(
            () ->
<think>我们被要求回答关于AJAX同步和异步的区别及工作原理的问题。根据引用资料,我们可以总结如下:1.**同步请求(Synchronous)**:-发送一个请求后,必须等待服务器响应结束(即请求完成)才能发送下一个请求。-在等待期间,用户不能进行其他操作,整个页面会被锁定(阻塞),用户体验较差。-同步请求会刷新整个页面。2.**异步请求(Asynchronous)**:-发送一个请求后,不需要等待服务器响应,可以继续发送其他请求。-通过回调函数处理服务器的响应,实现局部刷新(只更新页面的部分内容),不会阻塞用户操作。-用户体验更好,因为页面不会完全刷新,用户可以在等待服务器响应的同时继续与页面交互。**工作原理**:-AJAX通过`XMLHttpRequest`对象(现代浏览器中也可以用`fetch`API)与服务器进行异步通信。-基本步骤(四步操作):1.创建`XMLHttpRequest`对象。2.设置请求方法和URL,并指定是否异步(通过`open`方法的第三个参数,`true`表示异步,`false`表示同步)。3.设置回调函数(通过`onreadystatechange`事件),在请求状态改变时处理响应。4.发送请求(`send`方法)。在回调函数中,我们检查请求的状态(`readyState`)和响应的状态码(`status`),当请求完成且成功时(`readyState`为4,`status`为200),我们可以获取响应数据并更新页面的部分内容。**引用说明**:-引用[1]和[3]解释了同步和异步的基本概念以及区别。-引用[3]和[4]详细描述了AJAX的工作原理,包括四步操作。-引用[2]和[5]提供了更多关于使用场景和代码实现的信息。现在,我们按照要求生成相关问题。</think>### AJAX同步与异步的区别及工作原理 #### **同步请求(Synchronous)** 1. **工作原理**: 发送请求后,浏览器会**阻塞用户操作**,必须等待服务器返回完整响应才能继续执行后续代码。期间页面处于“冻结”状态。 代码示例: ```javascript let xhr = new XMLHttpRequest(); xhr.open('GET', '/api/data', false); // 第三个参数false表示同步 xhr.send(); console.log(xhr.responseText); // 需等待响应完成后才执行 ``` 2. **核心特点**: - 阻塞式交互,用户体验差 - 刷新整个页面 - 适用场景:需严格顺序执行的操作(如支付确认)[^3][^5] --- #### **异步请求(Asynchronous)** 1. **工作原理**: 通过事件驱动模型实现非阻塞通信: - 创建`XMLHttpRequest`对象 - 绑定`onreadystatechange`回调函数 - 服务器返回数据后触发回调,局部更新DOM ```javascript let xhr = new XMLHttpRequest(); xhr.open('GET', '/api/data', true); // true表示异步 xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { document.getElementById("content").innerHTML = xhr.responseText; // 局部刷新 } }; xhr.send(); console.log("请求已发送,无需等待"); // 立即执行 ``` 2. **核心特点**: - 非阻塞式交互,用户可继续操作页面 - 仅刷新局部内容(如动态加载评论) - 通过回调函数/`Promise`处理响应[^1][^4] --- #### **关键区别总结** | **特性** | 同步请求 | 异步请求 | |----------------|----------------------------|----------------------------| | **用户体验** | 页面卡顿,操作被阻塞 | 流畅,用户可继续交互 | | **刷新范围** | 整个页面重载 | 局部DOM更新 | | **代码执行** | 顺序执行,需等待响应 | 非阻塞,回调函数处理结果 | | **适用场景** | 强依赖顺序的操作(如表单提交)| 动态加载数据、实时搜索等[^2] | #### **AJAX技术本质** 基于`XMLHttpRequest`对象(或现代`fetch API`),利用JavaScript在后台与服务器交换数据,实现**无刷新更新页面**。其异步模式通过事件循环机制实现:当主线程发送请求后,由浏览器网络线程处理通信,响应到达后通过回调函数通知主线程[^4][^5]。 > 优势:提升用户体验,减少带宽消耗; > 局限:增加服务器压力,SEO不友好[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值