为了账号安全,请及时绑定邮箱和手机立即绑定

Java组合异步编程(1)

标签:
Java

您好,我是湘王,这是我的慕课手记,欢迎您来,欢迎您再来~


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

https://img1.sycdn.imooc.com//636b9e050001cf5202860524.jpg

 



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

public static void doSomethingElse() {
   try {
      System.out.println("doSomethingElse...");
      Thread.sleep(1_000);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
}

public static void executeComputation() {
   try {
      System.out.println("executeComputation...");
      Thread.sleep(2_000);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
}

// 使用Future
public static void testExecutor() throws InterruptedException, ExecutionException {
   // 申请线程池执行
   ExecutorService es = Executors.newSingleThreadExecutor();
   Future<Integer> f = es.submit(() -> {
      System.out.println(Thread.currentThread().getName());
      // 执行线程操作
      executeComputation();
      return 9527;
   });
   // 其他耗时操作
   doSomethingElse();
   System.out.println(f.get());
   es.shutdown();
}


 

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

https://img1.sycdn.imooc.com//636b9e820001d17808990593.jpg

 

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


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

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

ExecutorService service = Executors.newFixedThreadPool(3);
System.out.println("main start ...");
Future<Integer> f1 = service.submit(() -> {
   System.out.println(Thread.currentThread().getName());
   // 执行线程操作
   executeComputation();
   return 9525;
});
Future<Integer> f2 = service.submit(() -> {
   System.out.println(Thread.currentThread().getName());
   // 执行线程操作
   executeComputation();
   return 9526;
});
Future<Integer> f3 = service.submit(() -> {
   System.out.println(Thread.currentThread().getName());
   // 执行线程操作
   executeComputation();
   return 9527;
});
System.out.println("main end ...");
service.shutdown();

 

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

现在换成CompletableFuture试试看

ExecutorService service = Executors.newFixedThreadPool(3);
System.out.println("main start ...");
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
   System.out.println("9525...");
   return 9525;
}, service);

CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
   System.out.println("9526...");
   return 9526;
}, service);

CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
   System.out.println("9527...");
   return 9527;
}, service);

CompletableFuture<Void> future = CompletableFuture.allOf(future1, future2, future3);
future.get();
System.out.println("main end ...");
service.shutdown();

 

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

 

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

// 两个CompletableFuture,全部任务执行完成才返回
public static void testAllOf() throws InterruptedException, ExecutionException {
   CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
   CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "world");

   CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2);
   // 返回值是void,不会合并结果
   System.out.println(combinedFuture.get());

   // 需要手动处理每个并行异步任务的结果
   String combined = Stream.of(future1, future2)
                     .map(CompletableFuture::join)
                     .collect(Collectors.joining(" "));
   // hello world
   System.out.println(combined);
}

 

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

 

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

// 两个CompletableFuture,只要有一个任务执行完成就返回
public static void testAnyOf() throws InterruptedException, ExecutionException {
   CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
   CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
      try {
         Thread.sleep(2000);
      } catch (Exception e) {
         e.printStackTrace();
      }
      return "world";
   });
   CompletableFuture<Object> combinedFuture = CompletableFuture.anyOf(future1, future2);
   // Hello World
   System.out.println(combinedFuture.get());
}


这更像唐伯虎点秋香中最后揭盖头的场景——只要揭了一个剩下的全部自己揭开

 



 

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


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消