• CompletableFuture.supplyAsync 表示创建带返回值的异步任务的,相当于ExecutorService submit(Callable task) 方法
  • CompletableFuture.runAsync 表示创建无返回值的异步任务
  • CompletableFuture.thenApply CompletableFuture.thenApplyAsync 表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中
    ( 注:job1执行结束后,将job1的方法返回值作为入参传递到job2中并立即执行job2。thenApplyAsync与thenApply的区别在于,前者是将job2提交到线程池中异步执行,实际执行job2的线程可能是另外一个线程,后者是由执行job1的线程立即执行job2,即两个job都是同一个线程执行的)
  • CompletableFuture.thenAccept thenAccept 同 thenApply 接收上一个任务的返回值作为参数,但是无返回值
  • CompletableFuture.thenRun thenRun 的方法没有入参,也没有返回值
  • CompletableFuture.exceptionally exceptionally方法指定某个任务执行异常时执行的回调方法,会将抛出异常作为参数传递到回调方法中。
  • CompletableFuture.whenComplete 是当某个任务执行完成后执行的回调方法,会将执行结果或者执行期间抛出的异常传递给回调方法,如果是正常执行则异常为null,回调方法对应的CompletableFuture的result和该任务一致,如果该任务正常执行,则get方法返回执行结果,如果是执行异常,则get方法抛出异常
  @Test
    public void test10() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
          if(true){
                throw new RuntimeException("test");
            }else{
                return 1.2;
        });
        //cf执行完成后会将执行结果和执行过程中抛出的异常传入回调方法,如果是正常执行的则传入的异常为null
        //所以下面两个参数a,b 分别对应cf的返回值,cf抛出的异常。一般而言,如果cf运行正常没有出异常的情况下,a就有值,而b就是null。而如果cf里面抛异常了,那a就是null,b就是异常参数传进来
        CompletableFuture<Double> cf2=cf.whenComplete((a,b)->{
            if(b!=null){
                log.error("cf执行异常,异常信息={}",b.getMessage());
            }else{
                log.info("cf执行正常,没有抛任何异常。且cf执行的结果={}",a);
        });
        //如果cf是正常执行的,cf2.get的结果就是cf执行的结果
        //如果cf是执行异常,则cf2.get会抛出异常
        System.out.println("cf2的结果="+cf2.get());
  • CompletableFuture.handle 跟whenComplete函数基本一致,区别在于handle的回调方法有返回值,必须要return一个值,且handle方法得到的CompletableFuture的执行结果与前一个CompletableFuture的执行结果无关
    测试案例
 @Test
    public void test10() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
            if(true){
                throw new RuntimeException("test");
            }else{
                return 1.2;
        });
        //cf执行完成后会将执行结果和执行过程中抛出的异常传入回调方法,如果是正常执行的则传入的异常为null
        CompletableFuture<String> cf2=cf.handle((a,b)->{
            if(b!=null){
                log.error("cf执行异常,异常信息={}",b.getMessage());
            }else{
                log.info("cf执行正常,没有抛任何异常。且cf执行的结果={}",a);
            //之所以加下面的代码,是因为handle函数里面需要有return返回值才行
            if(b!=null){
                return "run error";
            }else{
                return "run succ";
        });
        //get的结果是cf2的返回值,跟cf没关系了
        System.out.println("cf2的返回值="+cf2.get()); 
        //打印结果:  cf2的返回值=run error
  • CompletableFuture.thenCombineCompletableFuture.thenAcceptBothCompletableFuture.runAfterBoth
    这三个方法都是将两个CompletableFuture组合起来,只有当那两个CompletableFuture都正常执行完了才会执行某个任务,区别在于,thenCombine会将两个任务的执行结果作为方法入参传递到指定方法中,且该方法有返回值;thenAcceptBoth同样将两个任务的执行结果作为方法入参,但是无返回值;runAfterBoth没有入参,也没有返回值。注意两个任务中只要有一个执行异常,则将该异常信息作为入参传递到这3个方法中。
  @Test
    public void test7() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            return 1.2;
        });
        CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
            return 3.2;
        });
        //cf和cf2的异步任务都执行完成后,会将其执行结果作为方法入参传递给cf3,且有返回值
        CompletableFuture<Double> cf3=cf.thenCombine(cf2,(a,b)->{
            log.info("thenCombine,a={},b={}",a,b);
            //打印结果a=1.2,b=3.2
            return a+b;
        });
        //cf和cf2的异步任务都执行完成后,会将其执行结果作为方法入参传递给cf3,无返回值
        CompletableFuture cf4=cf.thenAcceptBoth(cf2,(a,b)->{
            log.info("thenAcceptBoth,a={},b={}",a,b);
            //打印结果a=1.2,b=3.2
        });
        //cf4和cf3都执行完成后,执行cf5,无入参,无返回值
        CompletableFuture cf5=cf4.runAfterBoth(cf3,()->{
          log.info("runAfterBoth,无入参,无返回值");
        });
        //等待子任务执行完成
        System.out.println("cf的返回结果="+cf.get());
        System.out.println("cf2的返回结果="+cf2.get());
        System.out.println("cf3的返回结果="+cf3.get());
        System.out.println("cf4的返回结果="+cf4.get());
        System.out.println("cf5的返回结果="+cf5.get());
        //打印结果:
      //cf的返回结果=1.2
      //cf2的返回结果=3.2
      //cf3的返回结果=4.4
      //cf4的返回结果=null
      //cf5的返回结果=null
  • CompletableFuture.applyToEitherCompletableFuture. acceptEither 还有CompletableFuture. runAfterEither。 这三个方法都是将两个CompletableFuture组合起来,只要其中一个CompletableFuture执行完了就会执行某个任务,其区别在于applyToEither会将已经执行完成的任务的执行结果作为方法入参,并有返回值;acceptEither同样将已经执行完成的任务的执行结果作为方法入参,但是没有返回值;runAfterEither没有方法入参,也没有返回值。注意两个任务中只要有一个执行异常,则将该异常信息作为指定任务的执行结果。
   @Test
    public void test8() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
            int i = random.nextInt()%10;
            try {
                TimeUnit.SECONDS.sleep(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            log.info("cf执行完毕");
            return 1.2;
        });
        CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
            int i = random.nextInt()%10;
            try {
                TimeUnit.SECONDS.sleep(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            log.info("cf2执行完毕");
            return 3.2;
        });
        //cf和cf2中任何一个先执行完,会将其执行结果作为方法入参传递给cf3,且有返回值
        CompletableFuture<Double> cf3=cf.applyToEither(cf2,(result)->{
            log.info("cf3开始执行了,接收到的result={},当前时间={}",result,LocalDateTime.now());
            int i = random.nextInt()%10;
            try {
                TimeUnit.SECONDS.sleep(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            log.info("cf3开始执行完毕");
            return result;
        });
        //cf和cf2的任何一个先执行完会将其执行结果作为方法入参传递给cf4,无返回值
        CompletableFuture cf4=cf.acceptEither(cf2,(result)->{
            log.info("cf4开始执行了,接收到的result={},当前时间={}",result,LocalDateTime.now());
            int i = random.nextInt()%10;
            try {
                TimeUnit.SECONDS.sleep(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            log.info("cf4开始执行完毕");
        });
        //cf4和cf3中任何一个执行完就立刻执行cf5,无入参,无返回值
        CompletableFuture cf5=cf4.runAfterEither(cf3,()->{
            log.info("cf5开始执行了");
        });
        try {
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();

测试结果:
在这里插入图片描述

  • CompletableFuture.thenCompose 这个函数跟CompletableFuture.thenApply 很相似。但是有点区别,thenApply()转换的是泛型中的类型,相当于将CompletableFuture<T> 转换生成新的CompletableFuture<U>
    而thenCompose()用来连接两个CompletableFuture,是生成一个新的CompletableFuture。
  @Test
    public void test9() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            return 1.2;
        });
        CompletableFuture<String> cf2= cf.thenCompose((param)->{
            log.info("param={}",param);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            return CompletableFuture.supplyAsync(()->{
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                return "job3 test";
            });
        });
      log.info("cf2的结果={}",cf2.get());
  • CompletableFuture.allOf 返回的CompletableFuture是多个任务都执行完成后才会执行,只要有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
 // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            throw new RuntimeException("test");
            //return 1.2;
        });
        CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
            return 2.2;
        });
        CompletableFuture<Double> cf3 = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(1300);
            } catch (InterruptedException e) {
            return 3.2;
        });
        //allof等待所有任务执行完成才执行cf4,如果有一个任务异常终止,则cf4.get时会抛出异常,都是正常执行,cf4.get返回null
        //如果cf,cf2,cf3中至少有一个任务出现了异常,那么下面的a就是null,b就是异常信息,如果所有任务都正常,那a也是null,b是null
        CompletableFuture cf4=CompletableFuture.allOf(cf,cf2,cf3).whenComplete((a,b)->{
            if(b!=null){
             log.error("cf,cf2,cf3中至少有一个任务出现了异常,异常信息={}",b.getMessage());
            }else{
                log.error("cf,cf2,cf3任务全部执行成功,a={}",a);
        });
        log.info("cf4执行完毕,结果={}",cf4.get());
  • CompletableFuture.anyOf anyOf 的含义是只要有任意一个 CompletableFuture 结束,就可以做 接下来的事情,而无须像 AllOf 那样,等待所有的 CompletableFuture 结束。但由于每个 CompletableFuture 的返回值类型都可能不同,任意一个, 意味着无法判断是什么类型,所以 anyOf 的返回值是 CompletableFuture<Object>类型
 @Test
    public void test11() throws Exception {
        // 创建异步执行任务:
        CompletableFuture<String> cf = CompletableFuture.supplyAsync(()->{
            log.info("cf执行开始了");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            log.info("cf执行开始结束");
           return  "xiaoming";
        });
        CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
            log.info("cf2执行开始了");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
            log.info("cf2执行开始结束");
            return 2.2;
        });
        CompletableFuture<Double> cf3 = CompletableFuture.supplyAsync(()->{
            log.info("cf3执行开始了");
            try {
                Thread.sleep(1300);
            } catch (InterruptedException e) {
            log.info("cf3执行开始结束");
            return 3.2;
        });
        //anyOf是只有一个任务执行完成,无论是正常执行或者执行异常,都会执行cf4,cf4.get的结果就是已执行完成的任务的执行结果
        CompletableFuture<Object> cf4=CompletableFuture.anyOf(cf,cf2,cf3).whenComplete((a,b)->{
            if(b!=null){
                log.info("cf4执行开始,a={},b={}",a,b.getMessage());
            }else{
                log.info("cf4执行开始,a={}",a);
        });
        log.info("cf4执行结果={}",cf4.get());
        TimeUnit.SECONDS.sleep(10);

CompletableFuture默认使用ForkJoinPool.commonPool()线程池,如果机器是单核的,则默认使用ThreadPerTaskExecutor,该类是一个内部类,每次执行execute都会创建一个新线程

@SneakyThrows private void test() { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return "任务A"; }).thenApplyAsync(s -> { System.out.println(s); return "任务B";
通过调用异步方法(方法后边加Async后缀),串联起来的CompletableFuture可以异步地执行(使用ForkJoinPool.commonPool())。 static void thenApplyAsyncExample() { CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> { assertTrue(Thread.currentThr
所谓异步调用其实就是实现一个可无需等待被调用函数的返回值而让操作继续运行的方法。在 Java 语言中,简单的讲就是另启一个线程来完成调用中的部分计算,使调用继续运行或返回,而不需要等待计算结果。但调用者仍需要取线程的计算结果。 JDK5新增了Future接口,用于描述一个异步计算的结果。虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却...
static void thenApplyExample() { CompletableFuture cf = CompletableFuture.completedFuture("message").thenApply(s -> { assertFalse(Thread.currentThread().isDaemon()); 本文是CompletableFuture类的功能和用例的指南- 作为Java 8 Concurrency API改进而引入。 2. Java中的异步计算 异步计算很难推理。通常我们希望将任何计算视为一系列步骤。但是在异步计算的情况下,表示为回调的动作往往分散在代码中或者深深地嵌套在彼此内部。当我们需要处理其中一个步骤中可能发生的错误时,情况变得更糟。 Future接口是Java 5中添加...
Java CompletableFuture继承了CompletionStage和Future接口。 CompletableFuture.thenApply继承自CompletionStage。 thenApply返回一个新的CompletionStage,当该阶段正常完成时,将使用该阶段的结果作为所提供函数的参数来执行该过程。 从Java文档中找到thenApply的方法声明。 <U> CompletionStage<U> thenApply(Function<? super
private ThreadPoolExecutor threadPoolExecutor; CompletableFuture.supplyAsync(() -> { 做第一件事情; return A; },threadPoolExecutor).thenRun(()->{
private void test() { CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<String>() { @Override public String get() { try {...
先来回顾下FutureFuture是JDK1.5中添加的接口,主要功能为:但Future也有着非常明显的缺点:上面介绍了Future的缺点,这些问题都可以通过类解决,主要方法有: 可以看出,supply开头的两个方法是有返回值的,而run开头的两个方法是没有返回值的,至于第二个方法传入的Executor,这个在编码中可以自定义; 功能:当前任务正常完成以后,可将当前任务的返回值作为参数传给下一个任务; 执行任务A,任务A执行完成之后,将任务A返回值作为参数传入给任务B,打印结果为3: 以工作中常
CompletableFuture是Java 8引入的一种异步编程工具,它可以帮助我们更方便地处理异步任务和并发操作。下面是一些玩转CompletableFuture的方法和技巧: 1. 创建CompletableFuture对象:可以使用CompletableFuture的静态工厂方法,比如CompletableFuture.supplyAsync()创建一个带有返回值的CompletableFuture对象,CompletableFuture.runAsync()创建一个不带返回值的CompletableFuture对象。 2. 组合多个CompletableFuture:可以使用thenCompose()方法将多个CompletableFuture进行串行组合,也可以使用thenCombine()方法将多个CompletableFuture进行并行组合。 3. 异常处理:使用exceptionally()方法可以在CompletableFuture发生异常时进行处理,使用handle()方法可以对异常进行处理并返回一个默认值。 4. 超时处理:使用orTimeout()方法可以设置CompletableFuture的超时时间,如果在指定时间内任务没有完成,则会抛出TimeoutException。 5. 并行处理:使用allOf()方法可以并行执行多个CompletableFuture,并等待它们全部完成。 6. 异步回调:可以使用whenComplete()、handle()、exceptionally()等方法来注册异步回调函数,在任务完成时执行相应的操作。 7. 取消任务:使用completeExceptionally()方法可以取消CompletableFuture任务的执行。 这些只是CompletableFuture的一些常见用法和技巧,你可以根据具体的需求进一步探索和玩转CompletableFuture。希望对你有所帮助!
报SQL异常Parameter index out of range (1 > number of parameters, which is 0). weixin_57295291: 谢谢看了一下是xml文件里面的参数 `#{}`上也加上了 ` ` 困扰了我一天我说怎么传参数都传不过来,感谢 解决:Linux下-bash: nohup: command not found或者bash: nohup: 未找到命令的问题 AbrahamCui: 写成nohub的+1表情包 高数复习笔记(同济 第七版 上下册) 烂人662: 怎么下载为文件