首页 > 编程语言 >【java】什么是 Future 和 CompletableFuture - 一篇文章快速入门 Java 异步编程

【java】什么是 Future 和 CompletableFuture - 一篇文章快速入门 Java 异步编程

时间:2024-10-31 20:16:40浏览次数:9  
标签:异步 java get 任务 Future CompletableFuture 线程

1. 引言

在现代 Java 编程中,异步编程变得越来越重要。随着多核处理器的普及,充分利用多线程可以大大提高程序性能和用户体验。在这种情况下,Future 和 CompletableFuture 成为处理异步任务的核心工具。


2. Future 是什么?

Future 的定义及基本概念

Future 是 Java 并发库中的接口,表示一个异步计算的结果。使用 Future 可以在提交任务时立即返回一个对象,通过该对象可以检查任务的执行状态和结果。

Future 的使用流程

  • 提交任务到 ExecutorService
  • 获取 Future 对象
  • 使用 Future.get() 方法阻塞等待任务执行完成并获取结果

Future 的局限性

  •  Future.get() 会阻塞当前线程直到任务完成
  • 无法链式处理任务(给 CompletableFuture 铺个垫)
  • 缺少对任务完成后的回调机制
  • 无法处理任务执行中的异常

 3. CompletableFuture 是什么?

CompletableFuture 的基本概念

CompletableFuture 是Java 8中引入的增强版Future,实现了Future 和 CompletionStage 接口,提供了一种异步编程的更优雅的方式。

CompletableFuture 的特点

  • 支持链式调用,通过 thenApply、thenAccept 等方法进行链式处理
  • 提供回调机制,允许在任务完成后自动执行其他操作
  • 内置异常处理方法,如 exceptionally 和 handle

与 Future 的区别与增强点

  • CompletableFuture 允许在非阻塞方式下检查任务的执行状态
  • 支持组合多个异步任务的执行
  • 提供更丰富的 API 用于异步任务管理

4. 使用示例

Future 使用示例

Future 相关方法:

  • cancel(boolean):尝试取消任务的执行。true: 任务成功被取消, false 任务已经完成或者无法取消。
  • isCancelled(): 检查任务是否被取消。true: 任务在完成之前就被取消了,否则返回 false。
  • isDone(): 检查任务是否已经完成,不论正常、异常还是被取消。true: 任务已经完成,否则返回 false。
  • get(): 阻塞当前线程,直到任务完成并返回结果。返回任务计算结果。
  • get(long, TimeUnit): 与 get() 类似,但是会给定时间范围,若在时间范围内任务没有完成,会抛出TimeoutException。其他情况与 get() 一致。

示例代码:

public class Main {

    private static ExecutorService executor = Executors.newFixedThreadPool(2); // 创建线程池

    public static void main(String[] args) throws Exception {

        long currentTime = System.currentTimeMillis(); // 获取当前时间戳

        Future<Integer> future = executor.submit(() -> {
            Thread.sleep(2000);
            return 42;
        }); // 提交任务到线程池,并且获得 Future 对象

        Integer result = future.get(); // get() 方法会阻塞程序,直到任务执行完毕
        long afterTime = System.currentTimeMillis();

        System.out.println("spend time : " + (afterTime - currentTime) + "  Result : " + result); // 输出执行时间以及获取到的结果

        executor.shutdown(); // 关闭线程池
    }

}

输出:

CompletableFuture 使用示例

CompletableFuture 相关方法非常之多,这里截图一部分:

示例代码:

public class Main {

    public static void main(String[] args) throws Exception {

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);// 任务1 返回 10
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);// 任务2 返回 20
        CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> 30);// 任务3 返回 30

        // 任务1计算完毕后调用的函数
        future1.thenAccept((res) -> {
            System.out.println("任务1计算完毕");
        });

        // 组合多个任务
        CompletableFuture<Void> combineFuture = CompletableFuture.allOf(future1, future2, future3).thenRun(() -> {
            int result = future1.join() + future2.join() + future3.join(); // join() 方法会阻塞线程, 但是这里阻塞的并不是我们的主线程, 下面会进行说明
            System.out.println("组合计算后的结果为: " + result);
        });

        System.out.println("程序运行完毕");


    }

}

执行结果:

说明:

  • supplyAsync(): 参数为需要异步的任务
  • thenAccept(): 表示 future1 对象任务执行后的回调函数
  • CompletableFuture.allOf(): 等待一组任务全部执行完毕后执行的回调函数

注意!!CompletableFuture 有相当多的方法,这里不可能一一详尽,更多的还需要读者去一一尝试。

另外,关于上述的 join() 方法,这个方法也会阻塞线程,但是由于我们相关的回调函数并不是在主线程中执行的,因此 join 方法阻塞的并不是主线程,而是 ForkJoinPool.commonPool() 中分配到的线程(该线程池是共享线程池,本文不作过多描述,需要的读者可以自行搜索)。

5. Future 和 CompletableFuture 的区别是什么?

首先需要从基本概念了解他们的区别:

  • Future:是一个接口,代表一个可能在未来某个时间完成的异步计算的结果。它的主要功能是获取计算结果,但不支持多个 Future 进行组合。
  • CompeltableFuture:是 Future 的一个具体实现,提供了更强大的功能,它不仅支持异步计算,还支持将多个异步任务组合在一起,支持回调机制和链式操作。

1. 任务组合

  • Future:不支持任务组合。
  • CompletableFuture:允许使用 then、thenAccept、thenCombine、allof 等方法来组合多个异步任务。使得代码更加清晰以及便于维护。

2. 异常处理

  • Future:使用 get() 方法获取结果时,如果计算出错,会抛出一个检查异常(ExecutionException)。处理异常比较繁琐。
  • CompletableFuture:提供了 exceptionally 和 handle 方法来处理异常,使得异常处理更加灵活、优雅。

3. 回调机制

  • Future:不支持回调函数,完成后需要通过 get() 方法阻塞扽得改。
  • CompletableFuture:允许通过 then 系列方法注册回调函数,计算完成后可以立即执行。

标签:异步,java,get,任务,Future,CompletableFuture,线程
From: https://blog.csdn.net/2401_82656016/article/details/143268694

相关文章

  • Java 多线程中的通信机制
    本篇文章讲述了“Java多线程的通信机制”,阅读时长大约为:10分钟一、引言“Java多线程中的等待与通知机制”是一种线程间通信方式,用来协调线程的执行顺序和资源共享。通过这样子的机制,线程可以避免忙等待,提高资源利用率和程序执行效率。二、Java多线程中的通信机制概......
  • JAVA面向对象编程(详细 全部)
    概念面向对象编程(Object-orientedProgramming,OOP)是一种广泛应用于软件开发的编程范式。它通过将数据和对数据操作的方法封装在一个独立的实体中,即对象,来组织和管理代码。面向对象编程强调在编程过程中模拟真实世界中的实体和其相互关系。定义类我们需要搞清楚几件事情:对象......
  • (开题报告)django+vuejavaweb学生宿舍管理系统论文+源码
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于学生宿舍管理系统的研究,现有研究多集中于传统管理模式或单一功能模块的实现。在国内外,传统的学生宿舍管理方式主要依赖人工操作,效......
  • JavaScript:六.函数
    函数用于封装一段完成特定功能的代码,相当于将包含一条或多条语句的代码块“包裹”起来,用户在使用时只需关心参数和返回值,就能完成特定的功能。函数的优势在于提高代码的复用性,降低程序维护的难度。 6.1函数的定义与调用自定义函数的语法格式如下。function函数名([参......
  • Java的异常处理
    异常处理异常的简单了解什么是异常?指的是程序在执行过程中,出现的非正常情况,如果不处理最终会导致JVM的非正常停止。异常的抛出机制Java中把不同的异常用不同的类表示,一旦发生某种异常,就‘创建该异常类型的对象’,并且抛出(throw)。然后程序员如果没有捕捉(catch)这个异常对象,那么......
  • java+vue计算机毕设高校党建管理平台设计与现实-以西藏民族大学为例【开题+程序+论文+
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,高校党建工作面临着新的机遇与挑战。特别是在西藏民族大学这样的特殊地域环境中,如何有效管理和推进党建工作,成为了一个亟待解......
  • Java基础篇 (一)(JDK安装教程 零基础谁都可以学会!!!)
    前言大家好,我是小斜。俗话说的好,十年树木,百年树人。欲成大事,必须要坚持不懈努力。学习编程也一样,只有通过日积月累地学习才能有质的飞跃!我在这里给刚入门的大伙们提几点小建议:1.知行合一,编程归根结底就是要我们把思考出来的东西,再让它通过代码实现的一个过程。如果仅仅停留......
  • Java基础篇(三)(超详细整理,建议收藏!!!)
    目录一、Java的诞生与发展历史    1.1Java的出生地:SUNMicrosystemsInc.1.2 Java技术体系   1.3 Java语言的特点1.4 Java程序的运行机制1.4.1 JVM与跨平台1.4.2 JVM、JRE、JDK1.5 java开发环境1.6 java开发流程1.6.1 结构化编程与面......
  • PHP和Java在后端开发上有哪些不同_1
    PHP和Java是两种广泛使用的后端开发语言,它们在多个方面具有显著的区别。PHP和Java在以下关键方面的不同:1.语言特性和开发环境;2.性能和速度;3.社区支持和资源;4.适用场景和项目类型;5.学习曲线和易用性。PHP作为一种动态脚本语言,被广泛用于快速开发和简单的网站项目,而Java作为一种强......
  • (教程)如何用 Java 读取和写入图像
    在这篇文章中,我将向您展示如何用Java读取和写入图像文件。我将演示两种不同的方法。第一种是使用 ImageIO,第二种是使用我们的 JDeli图像库。如果您只是在寻找图像查看器,JDeli包含一个内置图像查看器。 如何在Java中读取和写入图像Java为图像提供了一种称为Buffe......