Java8异步类CompletableFuture详解

1、前言

学习java基础时候多线程使用我们首先学习的 RunableFutureThreadExecutorServiceCallable等相关类,在我们日常工作或者学习中有些场景并不满足我们需求,JDK8引入了一个新的类 CompletableFuture 来解决之前得问题, CompletableFuture 实现了 Future 接口和 CompletionStage 。因此 CompletableFuture是对 Futrue的功能增强包含了Future的功能。从继承的另一个 CompletionStage 的名称来看完成阶段性的接口,接下来了解一下 CompletableFuture 的一些基本情况以及使用和注意事项。

2、CompletableFuture使用

CompletableFuture提供了几十种方法,辅助我们的异步任务场景。这些方法包括创建异步任务、任务异步回调、多个任务组合处理等方面,JDK8设计出CompletableFuture。CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。

自定义线城池,一下代码都会使用到


   static ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
        int count = 1;

        @Override
        public Thread newThread(Runnable runnable) {
            return new Thread(runnable, "completableFuture-executor-" + count++);
        }
    });

2.1创建异步任务

  • runAsync 用于构建一个没有入参也没有出参的任务;

  • supplyAsync 用于构建一个没有入参但是有出参的任务

    runAsync和supplyAsync可以指定线程池,如果不指定,则使用ForkJoinPool的commonPool线程池

    先看源码

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        return asyncSupplyStage(asyncPool, supplier);
    }

    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }

    public static CompletableFuture<Void> runAsync(Runnable runnable) {
        return asyncRunStage(asyncPool, runnable);
    }

    public static CompletableFuture<Void> runAsync(Runnable runnable,
                                                   Executor executor) {
        return asyncRunStage(screenExecutor(executor), runnable);
    }

runAsync执行CompletableFuture任务,没有返回值。

    /**
     * runAsync执行CompletableFuture任务,没有返回值。
     */
    public static void runAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束");

        });
        System.out.println("异步线程执行状态" + completableFuture.isDone());
        System.out.println("主线程正在执行");
        System.out.println("异步线程执行状态" + completableFuture.isDone());
        System.out.println(completableFuture.get());
    }

执行结果

异步线程执行状态false
completableFuture-当前线程名称:ForkJoinPool.commonPool-worker-9
异步线程执行执行结束
null

supplyAsync执行CompletableFuture任务,支持返回值-使用自定义线城池

public static void supplyAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            System.out.println("异步线程执行执行结束");
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------supplyAsyncExample-----正在执行");
        System.out.println(completableFuture.join());
        executor.shutdown(); // 线程池需要关闭
    }

执行结果

主线程-------supplyAsyncExample-----正在执行
completableFuture2-当前线程名称:completableFuture-executor-1
异步线程执行执行结束
msg-异步线程执行结束

2.2任务异步回调

2.2.1 thenRun/thenRunAsync

不关心上一个任务的执行返回结果,无参数,无返回值

CompletableFuture的thenRun方法,通俗点讲就是,做完第一个任务后,再做第二个任务。某个任务执行完成后,执行回调方法;但是前后两个任务没有参数传递,第二个任务也没有返回值

如果你执行第一个任务的时候,传入了一个自定义线程池:

  • 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池
  • 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池
public CompletableFuture<Void> thenRun(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action);

thenRun代码

   public static void thenRunExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束,当前线程"+Thread.currentThread().getName());
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenRunExample-----正在执行1");
        CompletableFuture<Void> voidCompletableFuture = completableFuture.thenRun(() -> {
            System.out.println("thenRunExample----正在执行第二个任务,当前线程"+Thread.currentThread().getName());
        });
        System.out.println("主线程-------thenRunExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线程池需要关闭

    }

执行结果

主线程-------thenRunExample-----正在执行1
主线程-------thenRunExample-----正在执行2
异步线程执行执行结束,当前线程completableFuture-executor-1
thenRunExample----正在执行第二个任务,当前线程completableFuture-executor-1
null

thenRunAsync代码-异步使用自定义线城池

  public static void thenRunAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
       
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java异步调用CompletableFuture是一种非常强大的工具,它可以帮助我们处理异步编程的复杂性。下面是一个简单的示例,展示了CompletableFuture的基本用法: ```java import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CompletableFutureExample { public static void main(String[] args) { // 创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 异步执行任务 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "Hello, World!"; }, executor); // 注册回调函数 future.thenAccept(result -> System.out.println("Result: " + result)); // 关闭线程池 executor.shutdown(); } } ``` 在上面的例子中,我们首先创建了一个线程池,然后使用`CompletableFuture.supplyAsync()`方法将任务异步执行。在这个示例中,任务会休眠1秒钟,然后返回一个字符串结果"Hello, World!"。 接下来,我们通过调用`thenAccept()`方法注册了一个回调函数,该函数会在任务完成后被调用,并且会打印出结果。 最后,我们关闭了线程池。 需要注意的是,CompletableFuture还提供了很多其他的方法,可以帮助我们实现更加复杂的异步编程逻辑,比如`thenApply()`、`thenCompose()`、`thenCombine()`等等。你可以根据具体的需求选择适合的方法来使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值