码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Java组合异步编程(1)


    您好,我是湘王,这是我的CSDN博客,欢迎您来,欢迎您再来~

    在《计算机干活的两种方式》中我们提到过同步和异步的区别。所谓同步就是事情只能一件接一件地顺着干,而不能跳过。比如外卖小哥送外卖只能一件一件地送,不能说一件先送一半再送另一件。而异步就可以不按顺序出牌,但是这种不按顺序需要以互不影响为前提。比如李雷问韩梅梅一个数学问题,但是韩梅梅一时答不出来,李雷就先去干其他的事情去了。等韩梅梅知道答案的时候,再给李雷打电话告诉他结果。就像这样子:

     

    Java也支持这种异步工作模式。还是以代码来举例。

    1. public static void doSomethingElse() {
    2. try {
    3. System.out.println("doSomethingElse...");
    4. Thread.sleep(1_000);
    5. } catch (InterruptedException e) {
    6. e.printStackTrace();
    7. }
    8. }
    9. public static void executeComputation() {
    10. try {
    11. System.out.println("executeComputation...");
    12. Thread.sleep(2_000);
    13. } catch (InterruptedException e) {
    14. e.printStackTrace();
    15. }
    16. }
    17. // 使用Future
    18. public static void testExecutor() throws InterruptedException, ExecutionException {
    19. // 申请线程池执行
    20. ExecutorService es = Executors.newSingleThreadExecutor();
    21. Future f = es.submit(() -> {
    22. System.out.println(Thread.currentThread().getName());
    23. // 执行线程操作
    24. executeComputation();
    25. return 9527;
    26. });
    27. // 其他耗时操作
    28. doSomethingElse();
    29. System.out.println(f.get());
    30. es.shutdown();
    31. }

    运行代码后,也可以看到异步的执行痕迹。这可以用流程图来表示:

     

    代码中的Futrure,就是那个可以通知李雷的「电话」。

    那么问题来了,如果李雷有好几个不懂的问题,分别问了韩梅梅、赵梅梅、魏梅梅,而且需要答案之间有先后顺序怎么办呢?(比如要先得到韩梅梅的答案,再拿到赵梅梅的答案才有用)也就是对这种有多个「异步」任务的情况,该如何处理?这就是Java8中CompletableFuture(组合异步编程)要解决的问题。还是用代码来说话。

    假如现在有三个异步任务,要求这三个异步任务能够「按顺序」执行,可以试着这么写:

    1. ExecutorService service = Executors.newFixedThreadPool(3);
    2. System.out.println("main start ...");
    3. Future f1 = service.submit(() -> {
    4. System.out.println(Thread.currentThread().getName());
    5. // 执行线程操作
    6. executeComputation();
    7. return 9525;
    8. });
    9. Future f2 = service.submit(() -> {
    10. System.out.println(Thread.currentThread().getName());
    11. // 执行线程操作
    12. executeComputation();
    13. return 9526;
    14. });
    15. Future f3 = service.submit(() -> {
    16. System.out.println(Thread.currentThread().getName());
    17. // 执行线程操作
    18. executeComputation();
    19. return 9527;
    20. });
    21. System.out.println("main end ...");
    22. service.shutdown();

    但是运行之后发现,无论如何,「System.out.println("main end ...");」这行代码都不会最后执行,这就达不到「按顺序」执行的要求了。

    现在换成CompletableFuture试试看:

    1. ExecutorService service = Executors.newFixedThreadPool(3);
    2. System.out.println("main start ...");
    3. CompletableFuture future1 = CompletableFuture.supplyAsync(() -> {
    4. System.out.println("9525...");
    5. return 9525;
    6. }, service);
    7. CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {
    8. System.out.println("9526...");
    9. return 9526;
    10. }, service);
    11. CompletableFuture future3 = CompletableFuture.supplyAsync(() -> {
    12. System.out.println("9527...");
    13. return 9527;
    14. }, service);
    15. CompletableFuture future = CompletableFuture.allOf(future1, future2, future3);
    16. future.get();
    17. System.out.println("main end ...");
    18. service.shutdown();

    运行后会发现9525、9526、9527三个任务虽然都是异步任务,但能够「按顺序」排列,满足了最初的要求。

    现在,更进一步,如果某个答案取决于两个不相干的问题的共同回答,该怎么实现呢?例如,李雷问韩梅梅,然后又问了赵梅梅,只有在都问她们两个人的情况下,她们才会说出答案,否则不给答案。

    1. // 两个CompletableFuture,全部任务执行完成才返回
    2. public static void testAllOf() throws InterruptedException, ExecutionException {
    3. CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello");
    4. CompletableFuture future2 = CompletableFuture.supplyAsync(() -> "world");
    5. CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2);
    6. // 返回值是void,不会合并结果
    7. System.out.println(combinedFuture.get());
    8. // 需要手动处理每个并行异步任务的结果
    9. String combined = Stream.of(future1, future2)
    10. .map(CompletableFuture::join)
    11. .collect(Collectors.joining(" "));
    12. // hello world
    13. System.out.println(combined);
    14. }

    这就是神奇的CompletableFuture组合异步编程。可以通过代码让不同的问题强制「同频」,这算不算乱点鸳鸯谱?

    当然,如果有同学觉得这很过分,也可以允许「只要有问了她们其中之一就立刻给答案」:

    1. // 两个CompletableFuture,只要有一个任务执行完成就返回
    2. public static void testAnyOf() throws InterruptedException, ExecutionException {
    3. CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello");
    4. CompletableFuture future2 = CompletableFuture.supplyAsync(() -> {
    5. try {
    6. Thread.sleep(2000);
    7. } catch (Exception e) {
    8. e.printStackTrace();
    9. }
    10. return "world";
    11. });
    12. CompletableFuture combinedFuture = CompletableFuture.anyOf(future1, future2);
    13. // Hello World
    14. System.out.println(combinedFuture.get());
    15. }
    16. 这更像唐伯虎点秋香中最后揭盖头的场景——只要揭了一个,剩下的全部自己揭开。


      感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

    17. 相关阅读:
      智能微秘书+FastGPT,打造你的超级微信助手!
      python面试题总结(一)
      Jenkins(5)容器化部署 及 Jenkins集群配置
      Decorators与类
      Shiro安全框架
      C++中为何需要函数
      Python selenium自动化操作Chrome浏览器
      软著申请流程
      【Java八股文总结】之面试题(二)
      嘉为蓝鲸携手东风集团、上汽零束再获信通院四项大奖
    18. 原文地址:https://blog.csdn.net/lostrex/article/details/127777267
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号