当前位置: 首页 > article >正文

CompletableFuture

在现代编程中,异步操作是提升程序性能和响应性的关键技术。Java 8 引入的CompletableFuture类,极大地简化了异步编程的复杂性,提供了一种强大且灵活的方式来处理异步任务及其结果。本文将深入探讨CompletableFuture的特性、使用方法以及在实际应用中的优势,并通过丰富的代码示例帮助读者全面掌握这一重要工具。

CompletableFuture 概述

CompletableFuture实现了FutureCompletionStage接口,它不仅能够获取异步任务的结果,还能在任务完成时进行各种操作,比如执行回调函数、组合多个异步任务等。与传统的Future相比,CompletableFuture具有以下显著特点:

  • 异步操作的链式调用:可以通过链式调用的方式,对异步任务进行一系列的操作,无需手动管理线程和等待任务完成。
  • 自动回调机制:当异步任务完成时,会自动触发注册的回调函数,无需额外的轮询或等待操作。
  • 支持多个异步任务的组合:能够方便地组合多个异步任务,如并行执行、按顺序执行、等待所有任务完成或等待任一任务完成等。

CompletableFuture 基本用法

1. 创建 CompletableFuture

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        // 创建一个异步任务,返回一个CompletableFuture对象
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟异步任务的执行,这里使用Thread.sleep模拟耗时操作
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务完成,返回结果";
        });

        // 获取异步任务的结果,这是一个阻塞操作
        try {
            String result = future.get();
            System.out.println("异步任务结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,通过CompletableFuture.supplyAsync方法创建了一个异步任务,该方法接受一个Supplier接口的实现,返回一个CompletableFuture对象。在supplyAsync方法中,定义了异步任务的具体逻辑,这里通过Thread.sleep模拟了一个耗时 2 秒的操作,最后返回任务结果。通过future.get()方法获取异步任务的结果,该方法会阻塞当前线程,直到任务完成并返回结果。

2. 异步任务完成后的回调

import java.util.concurrent.CompletableFuture;

public class CompletableFutureCallbackExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务完成";
        }).thenAccept(result -> {
            System.out.println("接收到任务结果: " + result);
        });

        // 主线程不能立即退出,否则异步任务可能无法执行
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在这段代码中,thenAccept方法用于注册一个回调函数,当异步任务完成并返回结果时,会自动调用该回调函数。thenAccept方法接受一个Consumer接口的实现,它会将异步任务的结果作为参数传递给回调函数。在示例中,回调函数只是简单地打印接收到的任务结果。

3. 处理异步任务的异常

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExceptionExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            if (Math.random() > 0.5) {
                throw new RuntimeException("任务执行出错");
            }
            return "任务完成";
        }).exceptionally(ex -> {
            System.out.println("捕获到异常: " + ex.getMessage());
            return "默认结果";
        }).thenAccept(result -> {
            System.out.println("最终结果: " + result);
        });

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

exceptionally方法用于处理异步任务执行过程中抛出的异常。它接受一个Function接口的实现,当异步任务抛出异常时,会调用该函数,将异常作为参数传递进去,函数返回一个默认值,作为最终的结果。在示例中,通过Math.random()模拟了任务可能抛出异常的情况,当异常发生时,exceptionally方法捕获异常并返回一个默认结果,然后thenAccept方法处理最终结果。

CompletableFuture 组合异步任务

1. 多个异步任务并行执行并等待所有任务完成

import java.util.concurrent.CompletableFuture;

public class CompletableFutureAllOfExample {
    public static void main(String[] args) {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1完成";
        });

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2完成";
        });

        CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);
        allOfFuture.join();

        try {
            System.out.println("任务1结果: " + future1.get());
            System.out.println("任务2结果: " + future2.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

CompletableFuture.allOf方法用于将多个CompletableFuture组合在一起,等待所有任务完成。allOf方法返回一个新的CompletableFuture<Void>,当所有传入的CompletableFuture都完成时,这个新的CompletableFuture也会完成。在示例中,创建了两个异步任务future1future2,然后使用allOf方法将它们组合起来,通过join方法等待所有任务完成,最后获取并打印每个任务的结果。

2. 多个异步任务并行执行并等待任一任务完成

import java.util.concurrent.CompletableFuture;

public class CompletableFutureAnyOfExample {
    public static void main(String[] args) {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1完成";
        });

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2完成";
        });

        CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);
        try {
            System.out.println("最先完成的任务结果: " + anyOfFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

CompletableFuture.anyOf方法用于将多个CompletableFuture组合在一起,只要其中任一任务完成,这个新的CompletableFuture就会完成,并返回最先完成的任务的结果。在示例中,创建了两个异步任务future1future2,使用anyOf方法将它们组合,通过get方法获取最先完成的任务结果并打印。

结语

感谢您的阅读!如果您对 CompletableFuture 或其他并发编程话题有任何疑问或见解,欢迎继续探讨。


http://www.kler.cn/a/532818.html

相关文章:

  • 解释 Java 中的垃圾回收机制,以及如何优化垃圾回收性能?
  • 深度求索DeepSeek横空出世
  • 2024美团秋招硬件开发笔试真题及答案解析
  • 手写MVVM框架-实现简单的数据代理
  • C++11中的bind
  • 交叉验证、精确率、召回率
  • 2. 【.NET Aspire 从入门到实战】--理论入门与环境搭建--.NET Aspire 概览
  • Docker使用指南(一)——镜像相关操作详解(实战案例教学,适合小白跟学)
  • C 语言 | 入门 | 先导课程
  • asp.netcore 有关jwt的依赖包介绍
  • 鸿蒙Harmony-双向数据绑定MVVM以及$$语法糖介绍
  • DeepSeek-V3:开源多模态大模型的突破与未来
  • 【力扣题解】922. 按奇偶排序数组 II
  • 蓝桥与力扣刷题(141 环形链表)
  • 鼠标拖尾特效
  • BUU17 [RoarCTF 2019]Easy Calc1
  • 游戏引擎学习第87天
  • P3078[USACO13MAR] Poker Hands S
  • leetcode——多数元素(java)
  • 使用mockttp库模拟HTTP服务器和客户端进行单元测试
  • 开发板上Qt运行的环境变量的三条设置语句的详解
  • 【R语言】获取数据
  • C++ Primer 多维数组
  • 【Uniapp-Vue3】iconfont图标库的使用
  • kubernetes 高可用集群搭建
  • 文献学习笔记:中风醒脑液(FYTF-919)临床试验解读:有效还是无效?