首页 > 编程语言 >java之使用CompletableFuture入门1

java之使用CompletableFuture入门1

时间:2024-09-28 20:24:41浏览次数:8  
标签:INFO TestMain java 入门 -- CompletableFuture com

Java 17

-

 

简介

JDK中异步执行任务。 源码:
// A Future that may be explicitly completed (setting its value and status), 
// and may be used as a CompletionStage, supporting dependent functions 
// and actions that trigger upon its completion.
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
    // ...
}

//
// 实现的2个接口

// A Future represents the result of an asynchronous computation.
public interface Future<V> {
    // ...
}

// A stage of a possibly asynchronous computation, 
// that performs an action or computes a value when another CompletionStage completes. 
public interface CompletionStage<T> {
    // ...
}
 

supplyAsync

注,这个自己用的比较多。   有返回值的任务。   supplyAsync 源码:

下文使用第一个。第二个可以自定义线程池。

  代码:
private static void testCompletableFuture1() {
    log.info("in testCompletableFuture");

    StopWatch sw = new StopWatch();

    sw.start();
    CompletableFuture<LocalDateTime> task = CompletableFuture.supplyAsync(()->{
        log.info("in CompletableFuture task");
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return LocalDateTime.now();
    });
    sw.stop();

    try {
        log.info("等待结果...");
        sw.start();
        LocalDateTime ldt = task.get();
        sw.stop();
        log.info("结果={}", ldt);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } catch (ExecutionException e) {
        throw new RuntimeException(e);
    } finally {
        log.info("耗时:{}毫秒,sw=\n{}", sw.getTotalTimeMillis(), sw.prettyPrint());
    }
}
  结果:
17:25:37.697 [main] INFO com.example.test.TestMain -- in testCompletableFuture
17:25:37.706 [ForkJoinPool.commonPool-worker-1] INFO com.example.test.TestMain -- in CompletableFuture task
17:25:37.706 [main] INFO com.example.test.TestMain -- 等待结果...
17:25:41.714 [main] INFO com.example.test.TestMain -- 结果=2024-09-28T17:25:41.713449200
17:25:41.749 [main] INFO com.example.test.TestMain -- 耗时:4010毫秒,sw=
StopWatch '': running time = 4010560200 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
003454300  000%  
4007105900  100%  

 

get:

ForkJoinPool.commonPool-worker-1,线程名,使用了一个 ForkJoinPool。

 

造异常

结果:task.get() 调用时排除异常,没有输出结果。

17:27:45.155 [main] INFO com.example.test.TestMain -- in testCompletableFuture 17:27:45.163 [ForkJoinPool.commonPool-worker-1] INFO com.example.test.TestMain -- in CompletableFuture task 17:27:45.163 [main] INFO com.example.test.TestMain -- 等待结果... 17:27:45.184 [main] INFO com.example.test.TestMain -- 耗时:3毫秒,sw= StopWatch '': running time = 3313300 ns --------------------------------------------- ns         %     Task name --------------------------------------------- 003313300  100%     Exception in thread "main" java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: 造异常 at com.example.test.TestMain.testCompletableFuture1(TestMain.java:81) at com.example.test.TestMain.main(TestMain.java:45) Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: 造异常 at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396) at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073) at com.example.test.TestMain.testCompletableFuture1(TestMain.java:75) ... 1 more Caused by: java.lang.RuntimeException: 造异常 at com.example.test.TestMain.lambda$testCompletableFuture1$0(TestMain.java:60) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

 

使用 exceptionally 处理异常

新增代码:

结果:task.get() 正常执行,没有抛出异常。

17:34:02.625 [main] INFO com.example.test.TestMain -- in testCompletableFuture 17:34:02.639 [ForkJoinPool.commonPool-worker-1] INFO com.example.test.TestMain -- in CompletableFuture task 17:34:02.640 [main] ERROR com.example.test.TestMain -- task 发生异常:e= java.util.concurrent.CompletionException: java.lang.RuntimeException: 造异常 at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1770) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: java.lang.RuntimeException: 造异常 at com.example.test.TestMain.lambda$testCompletableFuture1$0(TestMain.java:60) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ... 6 common frames omitted 17:34:02.646 [main] INFO com.example.test.TestMain -- 等待结果... 17:34:02.647 [main] INFO com.example.test.TestMain -- 结果=1970-01-01T00:00 17:34:02.682 [main] INFO com.example.test.TestMain -- 耗时:14毫秒,sw= StopWatch '': running time = 14376300 ns --------------------------------------------- ns         %     Task name --------------------------------------------- 014364800  100%   000011500  000%    

 

注,这里时造了一个RuntimeException 异常,可以进一步造一个 InterruptedException 试试(TODO)。

 

构造器创建

通过 构造函数创建 CompletableFuture 对象:

CompletableFuture<String> task = new CompletableFuture<>();

代码:

private static void testCompletableFuture0() {
    CompletableFuture<String> task = new CompletableFuture<>();
    log.info("task={}, {}, {}", task.isCancelled(), task.isDone(), task.isCompletedExceptionally());

    Thread nt = new Thread(() ->{
        log.info("Thread nt 1");
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("Thread nt 2");

        task.complete("nt done.");
    });
    nt.start();

    try {
        log.info("task.get()={}", task.get());
        log.info("task.isx3={}, {}, {}", task.isCancelled(), task.isDone(), task.isCompletedExceptionally());
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } catch (ExecutionException e) {
        throw new RuntimeException(e);
    }

    log.info("end");
}

结果:

19:36:26.363 [main] INFO com.example.test.TestMain -- task=false, false, false
19:36:26.369 [Thread-0] INFO com.example.test.TestMain -- Thread nt 1
19:36:30.381 [Thread-0] INFO com.example.test.TestMain -- Thread nt 2
19:36:30.382 [main] INFO com.example.test.TestMain -- task.get()=nt done.
19:36:30.382 [main] INFO com.example.test.TestMain -- task.isx3=false, true, false
19:36:30.382 [main] INFO com.example.test.TestMain -- end

 

死锁

注释掉上面的 “// task.complete("nt done.");”,此时,程序无法停止。

结果:

task.get() 一直卡住了。

19:38:49.402 [main] INFO com.example.test.TestMain -- task=false, false, false
19:38:49.412 [Thread-0] INFO com.example.test.TestMain -- Thread nt 1
19:38:53.419 [Thread-0] INFO com.example.test.TestMain -- Thread nt 2

 

runAsync

没有返回值。   runAsync 源码:

  代码:
// 调用:
// testCompletableFuture2(1); // 无异常
// testCompletableFuture2(2); // 造异常

private static void testCompletableFuture2(int ctl) {
    log.info("ctl={}", ctl);

    // 形参为 Void
    CompletableFuture<Void> task = CompletableFuture.runAsync(()->{
        log.info("task 1");

        if (ctl % 2 == 0) {
            throw new RuntimeException("异常ctl=" + ctl);
        }

        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            log.error("task ex");
            throw new RuntimeException(e);
        }
        log.info("task 3");
    });
    //                .exceptionally(ex->{ // 处理异常
    //            log.error("exceptionally 处理异常:ex=", ex);
    //            return null;
    //        });

    try {
        log.info("2");
        var x = task.get();
        log.info("3.x={}", x);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } catch (ExecutionException e) {
        throw new RuntimeException(e);
    } finally {
        log.info("4.task.isx3={}, {}, {}", task.isCancelled(), task.isDone(), task.isCompletedExceptionally());
    }

    log.info("end");
}
结果:
20:03:37.633 [main] INFO com.example.test.TestMain -- ctl=1 20:03:37.646 [main] INFO com.example.test.TestMain -- 2 20:03:37.646 [ForkJoinPool.commonPool-worker-1] INFO com.example.test.TestMain -- task 1 20:03:41.655 [ForkJoinPool.commonPool-worker-1] INFO com.example.test.TestMain -- task 3 20:03:41.656 [main] INFO com.example.test.TestMain -- 3.x=null 20:03:41.657 [main] INFO com.example.test.TestMain -- 4.task.isx3=false, true, false 20:03:41.658 [main] INFO com.example.test.TestMain -- end   20:03:41.658 [main] INFO com.example.test.TestMain -- ctl=2 20:03:41.658 [main] INFO com.example.test.TestMain -- 2 20:03:41.658 [ForkJoinPool.commonPool-worker-1] INFO com.example.test.TestMain -- task 1 20:03:41.675 [main] INFO com.example.test.TestMain -- 4.task.isx3=false, true, true Exception in thread "main" java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: 异常ctl=2 at com.example.test.TestMain.testCompletableFuture2(TestMain.java:85) at com.example.test.TestMain.main(TestMain.java:50) Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: 异常ctl=2 at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396) at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073) at com.example.test.TestMain.testCompletableFuture2(TestMain.java:80) ... 1 more Caused by: java.lang.RuntimeException: 异常ctl=2 at com.example.test.TestMain.lambda$testCompletableFuture2$0(TestMain.java:62) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

 

使用 exceptionally 处理异常

和 前面一样,不过,返回值为 return null。

修改的代码:

结果:

20:08:59.546 [main] INFO com.benzl.tl.back.api.TestMain -- ctl=1 20:08:59.558 [ForkJoinPool.commonPool-worker-1] INFO com.benzl.tl.back.api.TestMain -- task 1 20:08:59.558 [main] INFO com.benzl.tl.back.api.TestMain -- 2 20:09:03.563 [ForkJoinPool.commonPool-worker-1] INFO com.benzl.tl.back.api.TestMain -- task 3 20:09:03.565 [main] INFO com.benzl.tl.back.api.TestMain -- 3.x=null 20:09:03.565 [main] INFO com.benzl.tl.back.api.TestMain -- 4.task.isx3=false, true, false 20:09:03.565 [main] INFO com.benzl.tl.back.api.TestMain -- end   20:09:03.565 [main] INFO com.benzl.tl.back.api.TestMain -- ctl=2 20:09:03.566 [main] INFO com.benzl.tl.back.api.TestMain -- 2 20:09:03.566 [ForkJoinPool.commonPool-worker-1] INFO com.benzl.tl.back.api.TestMain -- task 1 20:09:03.580 [ForkJoinPool.commonPool-worker-1] ERROR com.benzl.tl.back.api.TestMain -- exceptionally 处理异常:ex= java.util.concurrent.CompletionException: java.lang.RuntimeException: 异常ctl=2 at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1807) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: java.lang.RuntimeException: 异常ctl=2 at com.benzl.tl.back.api.TestMain.lambda$testCompletableFuture2$0(TestMain.java:62) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) ... 6 common frames omitted 20:09:03.596 [main] INFO com.benzl.tl.back.api.TestMain -- 3.x=null 20:09:03.597 [main] INFO com.benzl.tl.back.api.TestMain -- 4.task.isx3=false, true, false 20:09:03.597 [main] INFO com.benzl.tl.back.api.TestMain -- end   Process finished with exit code 0

注意,“4.task.isx3=false, true, false”,只有 中间一个 true 了。

 

---end---

 

或许还要写更多内容,更高级点的,比如,线程池、多个CompletableFuture对象 配合使用等……

 

参考资料

1、通俗易懂讲 CompletableFuture 

https://www.cnblogs.com/cyrus-s/p/15485182.html

posted @ 2021-10-30 15:49  三木同学

2、1.java多线程之FutureTask、Future、CompletableFuture
2024-04-09
https://developer.aliyun.com/article/1478152
作者:程序三两行

3、

 

ben发布于博客园

ben发布于博客园

标签:INFO,TestMain,java,入门,--,CompletableFuture,com
From: https://www.cnblogs.com/luo630/p/18438202

相关文章

  • 基于JavaWeb技术的在线考试系统设计与实现(11551)
     有需要的同学,源代码和配套文档领取,加文章最下方的名片哦一、项目演示项目演示视频二、资料介绍完整源代码(前后端源代码+SQL脚本)配套文档(LW+PPT+开题报告)远程调试控屏包运行三、技术介绍Java语言SSM框架SpringBoot框架Vue框架JSP页面Mysql数据库IDEA/Eclipse开发四、项......
  • Javax Validation 自定义注解校验(身份证号校验)
    一、场景分析我们使用SpringMVC在Controller层,对身份证号进行数据校验的话,经常采用以下方式:@RestController@RequiredArgsConstructor@RequestMapping("member")publicclassMemberController{//身份证号码正则表达式Stringregex="^(^[1-9]\\d{5}(18|......
  • Java的枚举类型使用指南
    测试代码:publicclassEnumTest{publicstaticvoidmain(String[]args){Sizes=Size.SMALL;Sizet=Size.LARGE;//s和t引用同一个对象?System.out.println(s==t);////是原始数据类型吗?System.out.println(s.getClass().isPrimitive());......
  • 线上教学平台(Java+springboot+lw+系统源码 +调试)
    线上教学平台摘要:在社会快速发展的影响下,使线上教学平台的管理和运营比过去十年更加理性化。依照这一现实为基础,设计一个快捷而又方便的网上线上教学平台系统是一项十分重要并且有价值的事情。对于传统的线上教学平台控制模型来说,网上线上教学平台系统具有许多不可比拟的优势......
  • 酒店管理系统(Java+springboot+lw+系统源码 +调试)
    摘 要21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高工作管理效率,促进其发展。论文主要是对酒店管理系统......
  • JavaScript深拷贝与浅拷贝
    由于对象采用的是引用赋值。所以直接用“=”,修改属性的时候也会将原来的变量改变掉。因此,就有了浅拷贝与深拷贝用{...obj}和object.assign表示浅拷贝,其只拷贝外围对象的一层,而不会拷贝多层。 方法二:使用Object.assign  深拷贝的实现其一是通过递归实现拷贝。其二lod......
  • [1199]基于JAVA的客诉反馈智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的客诉反馈智慧管理系统的设计与实现指导老师(一)选题的背景和意义开题报告背景及意义:在当前以客户为中心的商业环境中,企业对客诉反馈管理系统的依赖程度日益增强。传统的客诉处理方式由于效率低下、信息流转不畅、......
  • [1195]基于JAVA的客服咨询智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的客服咨询智慧管理系统的设计与实现指导老师(一)选题的背景和意义选题背景与意义:随着信息技术的飞速发展和互联网应用的普及,客户服务已成为企业提升品牌形象、维护客户关系及优化服务质量的关键环节。传统的客服系......
  • [1189]基于JAVA的客户智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的客户智慧管理系统的设计与实现指导老师(一)选题的背景和意义背景:在当今信息化社会,企业运营日益依赖于高效、精准的数据管理和客户服务流程。客户关系管理(CRM)作为现代企业管理的核心环节,对企业的市场竞争力和持续发......
  • [1181]基于JAVA的宠物门诊智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的宠物门诊智慧管理系统的设计与实现指导老师(一)选题的背景和意义选题背景与意义:随着社会经济水平的提高和人们生活质量的变化,宠物已逐渐成为许多家庭的重要成员,宠物医疗服务的需求也日益增长。传统的宠物门诊管理......