Java8 CompletableFuture 异步执行操作

 更新时间:2021年06月22日 18:02:04   作者:ACGkaka_  
CompletableFuture是java8提供的基于异步操作的封装,日常开发中经常会用到,接下来通过本文给大家介绍Java8 CompletableFuture 异步执行操作,感兴趣的朋友一起看看吧

1.简介

CompletableFuture 是 JDK8 提供的一个异步执行工具。

示例1:

public static void main(String[] args) throws ExecutionException, InterruptedException {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        for (int i = 0; i < 3; i++) {
            System.out.println(i);
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException ignored) {
            }
        }
        System.out.println("Future Finished.");
    });
    System.out.println("Main Thread Finished.");
    future.get();
}

输出结果1:

2.异步执行

CompletableFuture 提供了两个方法用于异步执行:

CompletableFuture.runAsync,没有返回值
CompletableFuture.supplyAsync,有返回值

示例:

public static void main(String[] args) throws ExecutionException, InterruptedException {
    // runAsync 没有返回值
    CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> System.out.println("future1 executed."));
    // supplyAsync 有返回值
    CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
        System.out.println("future2 executed.");
        return "result";
    });

    System.out.println("future1.get(): " + future1.get());
    System.out.println("future2.get(): " + future2.get());
}

输出结果:

3.守护线程

CompletableFuture返回的Future默认为守护线程,如果不调用get()获取结果,主线程结束后会自动结束。主要有以下4种情景:

  • 情景1: 执行时间 > 主线程时间,异步线程会执行
  • 情景2: 执行时间 > 主线程,是守护线程,会被杀死,异步线程不会执行
  • 情景3: 执行时间 > 主线程,但是不是守护线程,不会被杀死,异步线程会执行
  • 情景4: ExecutorService.submit(),默认不是守护线程,不会被杀死,异步线程会执行

示例:

public static void main(String[] args) {
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    // 1.执行时间 < 主线程,会打印
    CompletableFuture<Void> future1 = CompletableFuture.runAsync(() ->
		System.out.println("Thread1 是否为守护线程 : " + Thread.currentThread().isDaemon()));

    // 2.执行时间 > 主线程,是守护线程,会被杀死,不会打印
    CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(3000L);
            System.out.println("Thread2 是否为守护线程 : " + Thread.currentThread().isDaemon());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }});

    // 3.执行时间 > 主线程,但是不是守护线程,不会被杀死,会打印
    CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(1000L);
            System.out.println("Thread3 等待1秒");
            System.out.println("Thread3 是否为守护线程 : " + Thread.currentThread().isDaemon());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }}, executorService);

    // 4.ExecutorService.submit(),默认不是守护线程,不会被杀死,会打印。
    executorService.submit(() -> {
        try {
            Thread.sleep(2000L);
            System.out.println("Thread4 等待2秒");
            System.out.println("Thread4 是否为守护线程 : " + Thread.currentThread().isDaemon());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }});

    // 主线程执行完毕
    System.out.println("Main Thread Finished.");
    executorService.shutdown();
}

输出结果2:

4.处理执行结果

CompletableFuture还封装了很多处理执行结果操作。操作太多,列举比较常用的几种:

thenAccept(): 对结果进行使用;
thenApply(): 对结果进行转换;
exceptionally(): 对异常进行处理;
whenComplete(): 相当于 thenAccept() + thenApply() + exceptionally().

示例:

public static void main(String[] args) {
    // thenAccept对结果进行使用
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(() -> "Thread1 Finished.").thenAccept(System.out::println);

    // thenApply对结果进行转换
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(() -> "Thread2 Finished.")
        .thenApply(s -> s + " + thenApply()")
        .thenAccept(System.out::println);

    // exceptionally对异常进行处理
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(() -> {throw new RuntimeException("Thread3 Failed.");})
        .exceptionally(Throwable::toString).thenAccept(System.out::println);

    // 主线程执行完毕
    System.out.println("------------------------------");
    System.out.println("Main Thread Finished.");
}

输出结果:

whenComplete() 示例:

public static void main(String[] args) throws ExecutionException, InterruptedException {
    // thenAccept对结果进行使用
    System.out.println("------------------------------");
    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Thread1 Finished.").whenComplete(new BiConsumer<String, Throwable>() {
        @Override
        public void accept(String s, Throwable throwable) {
            System.out.println("result: " + s);
            System.out.println("throwable: " + throwable);
        }
    });

    // exceptionally对异常进行处理
    System.out.println("------------------------------");
    CompletableFuture.supplyAsync(() -> {
        throw new RuntimeException("Thread3 Failed.");
    }).whenComplete(new BiConsumer<Object, Throwable>() {
        @Override
        public void accept(Object s, Throwable throwable) {
            System.out.println("result: " + s);
            System.out.println("throwable: " + throwable);
        }
    });

    System.out.println("------------------------------");
    System.out.println("future.get(): " + future.get());

    // 主线程执行完毕
    System.out.println("------------------------------");
    System.out.println("Main Thread Finished.");
}

输出结果:

整理完毕,完结撒花~

以上就是Java8 CompletableFuture 异步执行的详细内容,更多关于Java8 CompletableFuture 异步执行的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot 整合mybatis+mybatis-plus的详细步骤

    SpringBoot 整合mybatis+mybatis-plus的详细步骤

    这篇文章主要介绍了SpringBoot 整合mybatis+mybatis-plus的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • Mybatis-plus全局id生成策略详解

    Mybatis-plus全局id生成策略详解

    这篇文章主要介绍了Mybatis-plus全局id生成策略详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Spring JPA之save方法示例详解

    Spring JPA之save方法示例详解

    这篇文章主要为大家介绍了Spring JPA之save方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Java构造器(构造方法)与方法区别说明

    Java构造器(构造方法)与方法区别说明

    这篇文章主要介绍了Java构造器(构造方法)与方法区别说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java中double精度丢失问题原因及解决办法

    Java中double精度丢失问题原因及解决办法

    使用Java double进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏0.0000**1,这篇文章主要给大家介绍了关于Java中double精度丢失问题原因及解决办法,需要的朋友可以参考下
    2024-01-01
  • 基于Java的MathML转图片的方法(示例代码)

    基于Java的MathML转图片的方法(示例代码)

    最近接到一个新需求mathML转图片怎么实现呢?刚开始还真是蒙圈了,不知道怎么实现,今天小编记录一种基于Java的MathML转图片的方法,感兴趣的朋友一起看看吧
    2021-06-06
  • java线程中断 interrupt 和 LockSupport解析

    java线程中断 interrupt 和 LockSupport解析

    这篇文章主要为大家介绍了java线程中断 interrupt 和 LockSupport示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • java计算机器人的运动范围

    java计算机器人的运动范围

    这篇文章主要为大家详细介绍了java计算机器人运动范围的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Java读取txt文件中的数据赋给String变量方法

    Java读取txt文件中的数据赋给String变量方法

    今天小编就为大家分享一篇Java读取txt文件中的数据赋给String变量方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 基于ChatGPT+SpringBoot实现智能聊天AI机器人接口并上线至服务器的方法

    基于ChatGPT+SpringBoot实现智能聊天AI机器人接口并上线至服务器的方法

    ChatGPT是一款基于自然语言处理技术的聊天机器人,ChatGPT可以模拟真实的人类对话,并能够更贴近用户的需求,提供更有价值的服务,这篇文章主要介绍了基于ChatGPT+SpringBoot实现智能聊天AI机器人接口并上线至服务器,需要的朋友可以参考下
    2023-02-02

最新评论