CompleteFuture与Future的比较

发布时间:2023年12月19日

在这里插入图片描述

CompleteFuture的介绍

CompletableFuture是Java 8提供的一种基于Future的异步编程的实现。它不仅可以代表异步计算的结果,还能够定义它完成之后的回调函数。它的实现在java.util.concurrent.CompletableFuture的包内。

CompletableFuture的实现涉及到JDK 8的几个新特性,如Lambda、Stream、线程池等,它允许把任务池、线程池和阻塞队列组合在一起,使得开发者可以更加简单地实现异步编程,对程序的执行性能也带来了一定的提升。

与Future相比,CompletableFuture的优势在于:

  1. 可以直接对多个任务进行链式、组合等处理,而不需要借助并发工具类。
  2. 实现了对任务编排的能力,可以轻松地组织不同任务的运行顺序、规则以及方式。

CompleteFuture的特点

CompletableFuture的特点主要包括异步执行、链式操作和灵活性强

  1. 异步执行:CompletableFuture允许任务在后台线程中异步执行,不会阻塞主线程,提高了应用程序的响应性和性能。
  2. 链式操作:CompletableFuture支持链式操作,可以方便地处理任务的依赖关系和结果转换。
  3. 灵活性强:相比于传统的Future接口,CompletableFuture更加灵活和强大,提供了丰富的方法来处理异步操作和多个任务的结果。

CompleteFuture的应用场景

CompletableFuture的应用场景主要包括异步编程、任务组合和并发编程

  1. 异步编程:在需要执行耗时操作的情况下,使用CompletableFuture可以实现异步执行,避免阻塞主线程,提高程序的响应性和性能。
  2. 任务组合:CompletableFuture支持链式操作,可以将多个异步任务组合在一起,按照指定的顺序和逻辑执行,实现任务的依赖关系和结果转换。
  3. 并发编程:在多线程环境下,CompletableFuture可以方便地处理多个任务的结果,避免线程间的竞争和同步问题,提高并发编程的效率和可靠性。

CompletableFuture的优缺点

CompletableFuture的优点主要包括简洁易用、支持异步编程、任务组合和并发编程等。它提供了一种简洁的方式来处理异步计算和任务组合,使得异步编程更加容易和高效。

然而,CompletableFuture也存在一些缺点,例如:

  1. 无法对多个任务进行链式调用:如果希望在计算任务完成后执行特定动作,比如发邮件,但CompletableFuture却没有提供这样的能力。
  2. 无法组合多个任务:如果运行了10个任务,并期望在它们全部执行结束后执行特定动作,那么在CompletableFuture中这是无能为力的。
  3. 没有异常处理:CompletableFuture接口中没有关于异常处理的方法。

在这里插入图片描述

Future的介绍

Future是Java中用于异步计算的一个接口。它提供了一种方式,允许将一个耗时的计算任务放到另一个线程中执行,而主线程可以继续处理其他任务。

在Future接口中,通常包含一些方法,如isDone()、get()、cancel()等。isDone()方法用于检查Future是否已经完成,get()方法用于获取Future的结果,cancel()方法用于取消Future的计算任务。

使用Future接口可以实现异步计算,提高程序的执行效率。当需要执行一个耗时的计算任务时,可以创建一个Future对象,然后将该对象传递给异步线程执行。异步线程执行完成后,可以通过Future对象获取计算结果。


Future的特点

Future的特点主要有以下几个方面:

  1. 表示异步操作未完成时的状态:Future对象可以表示一个异步操作是否完成,如果异步操作未完成,Future对象的状态为未完成,如果异步操作完成,Future对象的状态为已完成。
  2. 可以用来获取异步操作完成后返回的结果:通过Future对象提供的get方法,可以获取异步操作完成后返回的结果。
  3. 不提供直接的方式来添加回调函数:Future不提供一种直接的方式来添加回调函数,处理操作完成后的结果或异常。
  4. 只能表示异步任务是否完成,而不能手动触发任务的完成或组合多个任务:Future只能表示异步任务是否完成,而不能手动触发任务的完成或组合多个任务。

Future的应用场景

Future的应用场景主要在并发编程中,当我们需要用到非阻塞的模型时,Future就显得尤为重要。

在Java多线程的三种实现中,无论是继承Thread类还是实现Runnable接口,都是异步的,并且主调函数无法获取到返回值。而Future则可以接收多线程的执行结果。具体来说,Future接收一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callable以便任务执行成功或失败后作出相应的操作。

采用Future修改的异步方法,在每次被异步调用以后会马上返回(无论异步方法体是否执行完成),Future就会监听异步任务执行状态(成功、失败),等到执行完成以后,就能通过Future.get()方法获取到异步返回的结果。也就是说,如果批量调用采用Future修饰的异步方法,程序不会阻塞等待,然后再遍历Future列表,即可获取到所有的异步结果(Future的内部机制是等所有的异步任务完成了才进行遍历)。这种请求耗时只会略大于耗时最长的一个Future修饰的方法。


Future的优缺点

Future的优点主要包括:

  1. 异步处理:Future允许将耗时的计算任务放到另一个线程中执行,不会阻塞主线程,提高了程序的执行效率。
  2. 链式操作:Future支持链式操作,可以方便地处理任务的依赖关系和结果转换。

然而,Future也存在一些缺点:

  1. 阻塞获取结果:当需要获取Future的结果时,如果计算还没有完成,会导致程序阻塞。这可能会影响程序的性能和响应性。
  2. 无法添加回调函数:Future不提供一种直接的方式来添加回调函数,处理操作完成后的结果或异常。这使得在异步操作完成后,无法直接进行特定的处理。

在这里插入图片描述

CompletableFuture和Future的区别

CompletableFuture和Future的区别主要体现在以下几个方面:

  1. 功能区别 :Future只能用于获取异步计算的结果,而CompletableFuture除了能获取异步计算的结果外,还可以用于组合多个异步任务,处理异常情况,以及在任务完成时执行回调函数等。
  2. 阻塞区别 :Future的get方法是阻塞的,如果异步计算没有完成,它会一直等待直到计算完成。而CompletableFuture的get方法也是阻塞的,但是它可以设置超时时间,如果在指定的时间内计算没有完成,它会抛出TimeoutException异常。
  3. 异常处理区别 :Future的异常处理比较麻烦,需要在任务执行时捕获异常,然后将异常封装到Future对象中返回。而CompletableFuture的异常处理比较简单,可以使用exceptionally方法或handle方法来处理异常情况。
  4. 组合任务区别 :Future不支持组合多个异步任务,需要使用ExecutorService的submit方法来提交多个任务,并使用Future对象来获取每个任务的结果。而CompletableFuture支持组合多个异步任务,可以使用thenCompose、thenCombine、thenAcceptBoth等方法来组合多个任务。

CompletableFuture和Future的关联关系

CompletableFuture和Future之间存在关联关系,因为CompletableFuture实现了Future接口。这意味着CompletableFuture可以作为Future使用,同时它还提供了更多功能,如链式操作、异常处理和组合任务等。

CompletableFuture在内部使用了一个子线程来执行任务,并且提供了异步计算的结果。当异步计算完成时,CompletableFuture会自动将结果设置为已完成状态,并且可以通过get方法获取结果。

与Future相比,CompletableFuture提供了更多的功能和灵活性。它支持链式操作,可以将多个异步任务组合在一起,并且可以在任务完成后执行特定的回调函数。此外,CompletableFuture还提供了异常处理机制,可以捕获和处理任务执行过程中抛出的异常。

因此,CompletableFuture是Future的扩展和增强,它提供了更多的功能和灵活性,适用于需要处理异步计算和组合多个任务的场景。


CompletableFuture和Future的使用示例

CompletableFuture使用示例

以下是一个使用CompletableFuture的示例:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, World!";
        });

        // 获取异步计算的结果
        String result = future.get();
        System.out.println(result);
    }
}

在这个示例中,我们使用CompletableFuture的supplyAsync方法创建了一个异步任务,该任务会返回一个字符串"Hello, World!"。然后,我们使用get方法获取异步计算的结果,并将其打印出来。这个示例演示了如何使用CompletableFuture来执行异步计算并获取结果。

Future使用示例

以下是一个使用Java Future的示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // 提交任务并获取Future对象
        Future<String> future = executor.submit(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, World!";
        });

        // 获取异步计算的结果
        String result = future.get();
        System.out.println(result);

        // 关闭ExecutorService
        executor.shutdown();
    }
}

在这个示例中,我们使用ExecutorService的submit方法提交了一个异步任务,该任务会返回一个字符串"Hello, World!"。然后,我们使用Future的get方法获取异步计算的结果,并将其打印出来。最后,我们关闭了ExecutorService以释放资源。这个示例演示了如何使用Java Future来执行异步计算并获取结果。

在这里插入图片描述

CompletableFuture应用步骤

在项目中使用CompletableFuture,可以按照以下步骤进行:

  1. 导入CompletableFuture类:首先,需要在项目中导入CompletableFuture类,以便使用其功能。
  2. 创建异步任务:使用CompletableFuture的静态方法supplyAsync或runAsync来创建异步任务。supplyAsync方法接受一个Supplier接口的实现类作为参数,用于定义异步任务的逻辑。runAsync方法接受一个Runnable接口的实现类作为参数,用于定义异步任务的逻辑。
  3. 链式操作:使用CompletableFuture的thenApply、thenAccept、thenRun等方法来链式操作异步任务。这些方法接受一个Function、Consumer或Runnable接口的实现类作为参数,用于定义链式操作的逻辑。
  4. 异常处理:使用CompletableFuture的exceptionally方法来处理异步任务中抛出的异常。exceptionally方法接受一个Function接口的实现类作为参数,用于定义异常处理的逻辑。
  5. 获取结果:使用CompletableFuture的get方法来获取异步计算的结果。get方法会阻塞当前线程,直到异步计算完成并返回结果。

以下是一个简单的示例代码,演示了如何在项目中使用CompletableFuture:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class CompletableFutureExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, World!";
        }).thenApply(result -> {
            // 链式操作:对结果进行处理
            return result.toUpperCase();
        }).thenAccept(result -> {
            // 链式操作:对结果进行处理并输出到控制台
            System.out.println(result);
        });

        // 获取异步计算的结果(如果需要)
        future.get();
    }
}

在上面的示例中,我们首先使用CompletableFuture的supplyAsync方法创建了一个异步任务,该任务会返回一个字符串"Hello, World!"。然后,我们使用thenApply方法对结果进行链式操作,将结果转换为大写字母。接着,我们使用thenAccept方法对结果进行链式操作,将结果输出到控制台。最后,我们使用get方法获取异步计算的结果(如果需要)。

在这里插入图片描述

文章来源:https://blog.csdn.net/zhangzehai2234/article/details/135074053
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。