Java8 CompletableFuture 异步执行操作

目录
  • 1.简介
  • 2.异步执行
  • 3.守护线程
  • 4.处理执行结果

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 异步执行的资料请关注我们其它相关文章!

(0)

相关推荐

  • 浅谈Java中spring 线程异步执行

    多线程并发处理起来通常比较麻烦,如果你使用spring容器来管理业务bean,事情就好办了多了.spring封装了Java的多线程的实现,你只需要关注于并发事物的流程以及一些并发负载量等特性,具体来说如何使用spring来处理并发事务: 1.了解 TaskExecutor接口 Spring的TaskExecutor接口等同于java.util.concurrent.Executor接口. 实际上,它存在的主要原因是为了在使用线程池的时候,将对Java5的依赖抽象出来. 这个接口只有一个方法exe

  • Java8 CompletableFuture详解

    Java 8来了,是时候学一下新的东西了.Java 7和Java 6只不过是稍作修改的版本,而Java 8将会发生重大的改进.或许是Java 8太大了吧?今天我会给你彻底地解释JDK 8中的新的抽象 – CompletableFuture.众所周知,Java 8不到一年就会发布,因此这篇文章是基于JDK 8 build 88 with lambda support的.CompletableFuture extends Future提供了方法,一元操作符和促进异步性以及事件驱动编程模型,它并不止步

  • Java创建多线程异步执行实现代码解析

    实现Runable接口 通过实现Runable接口中的run()方法 public class ThreadTest implements Runnable { public static void main(String[] args) { Thread thread = new Thread(new ThreadTest()); thread.start(); } @Override public void run() { System.out.println("Runable 方式创建的新

  • Java8新的异步编程方式CompletableFuture实现

    一. Future JDK 5引入了Future模式.Future接口是Java多线程Future模式的实现,在java.util.concurrent包中,可以来进行异步计算. Future模式是多线程设计常用的一种设计模式.Future模式可以理解成:我有一个任务,提交给了Future,Future替我完成这个任务.期间我自己可以去做任何想做的事情.一段时间之后,我就便可以从Future那儿取出结果. Future的接口很简单,只有五个方法. public interface Future<

  • Java使用多线程异步执行批量更新操作方法

    写在前面: 相信不少开发者在遇到项目对数据进行批量操作的时候,都会有不少的烦恼,尤其是针对数据量极大的情况下,效率问题就直接提上了菜板.因此,开多线程来执行批量任务是十分重要的一种批量操作思路,其实这种思路实现起来也十分简单,就拿批量更新的操作举例: 整体流程图 步骤 获取需要进行批量更新的大集合A,对大集合进行拆分操作,分成N个小集合A-1 ~ A-N . 开启线程池,针对集合的大小进行调参,对小集合进行批量更新操作. 对流程进行控制,控制线程执行顺序. 按照指定大小拆分集合的工具类 impo

  • Java8 CompletableFuture 异步执行操作

    目录 1.简介 2.异步执行 3.守护线程 4.处理执行结果 1.简介 CompletableFuture 是 JDK8 提供的一个异步执行工具. 示例1: public static void main(String[] args) throws ExecutionException, InterruptedException { CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { for (int i

  • JS异步执行结果获取的3种解决方式

    前言 JS异步执行机制具有非常重要的地位,尤其体现在回调函数和事件等方面. 但异步有时候很方便,有时候却很让人恼火,下面来总结一下异步执行结果获取的方法 回调 这是最传统的方法了,也是最简单的,如下代码 function foo(cb) { setTimeout(function() { cb(1); // 通过参数把结果返回 }, 2000); } foo(function(result) { // 调用foo方法的时候,通过回调把方法返回的数据取出来 console.log(result);

  • Java并发 CompletableFuture异步编程的实现

    前面我们不止一次提到,用多线程优化性能,其实不过就是将串行操作变成并行操作.如果仔细观察,你还会发现在串行转换成并行的过程中,一定会涉及到异步化,例如下面的示例代码,现在是串行的,为了提升性能,我们得把它们并行化. // 以下两个方法都是耗时操作 doBizA(); doBizB(); //创建两个子线程去执行就可以了,两个操作已经被异步化了. new Thread(()->doBizA()) .start(); new Thread(()->doBizB()) .start(); 异步化,是

  • CompletableFuture 异步编排示例详解

    目录 从Future聊起 CompletableFuture 创建异步任务 异步回调 异步编排 串行 AND OR Future 机制扩展 CompletableFuture 实践 从Future聊起 Future是java 1.5引入的异步编程api,它表示一个异步计算结果,提供了获取异步结果的能力,解决了多线程场景下Runnable线程任务无法获取结果的问题. 但是其获取异步结果的方式并不够优雅,我们必须使用Future.get的方式阻塞调用线程,或者使用轮询方式判断 Future.isDo

  • Java CompletableFuture 异步超时实现深入研究

    目录 前言 常见使用方式 存在的问题 分析 现有做法 解决方式 JDK 9 JDK 8 前言 作者:京东科技 张天赐 JDK 8 是一次重大的版本升级,新增了非常多的特性,其中之一便是 CompletableFuture.自此从 JDK 层面真正意义上的支持了基于事件的异步编程范式,弥补了 Future 的缺陷. 在我们的日常优化中,最常用手段便是多线程并行执行.这时候就会涉及到 CompletableFuture 的使用. 常见使用方式 下面举例一个常见场景. 假如我们有两个 RPC 远程调用

  • PHP编程实现脚本异步执行的方法

    本文实例讲述了PHP编程实现脚本异步执行的方法.分享给大家供大家参考,具体如下: php语言得用fsockopen()函数,实现脚本异步运行,代码如下 异步请求函数(用debug参数若为true则为用为调试,开启调试可以看到异步的执行情况,但是失去异步的效果) main.php <?php function request_by_fsockopen($url,$post_data=array(),$debug=false){ $url_array = parse_url($url); $host

  • 4种PHP异步执行的常用方式

    本文为大家讲述了php异步调用方法,分享给大家供大家参考,具体内容如下 客户端与服务器端是通过HTTP协议进行连接通讯,客户端发起请求,服务器端接收到请求后执行处理,并返回处理结果. 有时服务器需要执行很耗时的操作,这个操作的结果并不需要返回给客户端.但因为php是同步执行的,所以客户端需要等待服务处理完才可以进行下一步. 因此对于耗时的操作适合异步执行,服务器接收到请求后,处理完客户端需要的数据就返回,再异步在服务器执行耗时的操作. 1.使用Ajax 与 img 标记 原理,服务器返回的htm

  • 深入PHP异步执行的详解

    Web服务器执行一个PHP脚本,有时耗时很长才能返回执行结果,后面的脚本需要等待很长一段时间才能继续执行.如果想实现只简单触发耗时脚本的执行而不等待执行结果就直接执行下一步操作,可以通过fscokopen函数来实现.PHP支持socket编程,fscokopen函数返回一个到远程主机连接的句柄,可以像使用fopen返回的句柄一样,对它进行fwrite.fgets.fread等操作.使用fsockopen连接到本地服务器,触发脚本执行,然后立即返回,不等待脚本执行完成,即可实现异步执行PHP的效果

  • Android加载对话框同时异步执行实现方法

    Android中通过子线程连接网络获取资料,同时显示加载进度对话框给用户的操作,需要Thread和Handler来完成,在Thread中执行比较耗时的代码,完成后再通过Handler发送消息给主线程,由主线程刷新UI. 在实现上比较的烦琐,为简化此方法,花了点时间封装了Thread和Handler,现在通过简单的代码就可以实现相同的功能,而把更多精力放到业务逻辑处理上! 效果如图:   复制代码 代码如下: LoadingDialog loadingDialog = new LoadingDia

随机推荐