java8 CompletableFuture_异步执行多个任务

前言

CompletableFuture是java8提供的基于异步操作的封装,日常开发中怎能不用上一番呢。
1)聚合多个异步任务

需求:多个tab页包含不同的表格数据,并且带分页,页面首次加载时需要显示第一页数据,并且在tab顶上显示总量,如下图所示:

各个表格数据从es中查询,涉及到计算,此处可以让前端调用多个接口来组装数据,但考虑到查询效率和网络交互,采用后端以多线程的形式查询,组合多个结果返回给前端,后端实现如下:
//所有订单
CompletableFuture<OrdersBo.Item> allOrdersFuture = fillAllOrders(pd, ordersBo);
//及时量订单
CompletableFuture<OrdersBo.Item> inTimeOrdersFuture = fillInTimeOrders(pd, ordersBo);
//超时量订单
CompletableFuture<OrdersBo.Item> timeOutFuture = fillOverTimeOrders(pd, ordersBo);
//失败量
CompletableFuture<OrdersBo.Item> failOrderFutrue = fillFailOrders(pd, ordersBo);
//异常量
CompletableFuture<OrdersBo.Item> exceptionOrderFuture = fillExceptionOrders(pd, ordersBo);

//聚合几个查询的结果返回给前端
CompletableFuture.allOf(allOrdersFuture, inTimeOrdersFuture, failOrderFutrue, timeOutFuture, exceptionOrderFuture).join();
return ordersBo;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
上述其实就是用到了CompletableFuture的特性,CompletableFuture.allOf()方法需要其中的每个异步任务都结束,配合join实现阻塞的效果,类似的还有很多方法,可以在不同的场景下使用,比如anyOf,当面临多份数据来源时,选择最快的一方。
CompletableFuture提供的api方法很多,我们可以将其归类来理解,首先是以then开头的方法,如thenAccept
凡是带accept的方法都没有返回值,接收的是一个消费者(Customer)
accept和acceptAsync的区别是,带Async的方法,可以异步执行,默认是使用forkjoinpool并且可以指定其他线程池。
以apply结尾的参数是接收的一个生产者(FUNCTION),具有返回值。
以run开头的对先前的执行结果不关心,执行完毕后直接执行下一个操作。
带Either的用在两个异步方法,只要取其中一个执行完毕就执行操作。
2)配合spring的@Async使用

在演示程序里,我定义了两个方法,分别是请求百度和请求新浪,我希望让这两个请求再我自定义的线程池中执行。其中用到的spring-web中的restTemplate来做请求,在具体方法中打印出当前执行的线程(为线程取名是很重要的哦,特别是线上发生问题能很好的通过工具定位),主要代码如下
   @Autowired
    private RestTemplate restTemplate;
    @Bean(name = "myExecutor")
    public Executor buildExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(3);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("hyq线程前缀-");
        executor.initialize();
        return executor;
    }

    @Async("myExecutor")
    public CompletableFuture<String> testBaidu(){
        System.out.println("baidu : "+Thread.currentThread().getName());
        ResponseEntity<String> result = restTemplate.getForEntity("https://www.baidu.com/", String.class);
        String body = result.getBody();
        return CompletableFuture.completedFuture(body);
    }

    @Async("myExecutor")
    public CompletableFuture<String> testSina(){
        System.out.println("sina: "+Thread.currentThread().getName());
        ResponseEntity<String> result =  restTemplate.getForEntity("https://www.sina.com.cn/", String.class);
        String body = result.getBody();
        return CompletableFuture.completedFuture(body);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3)总结

CompletableFuture为我们封装了各种异步处理的特性,能有效的改善我们程序的性能,让我们能得心应手的实现各种复杂逻辑。
————————————————
版权声明:本文为CSDN博主「独行侠梦」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012811805/article/details/84843960

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用`CompletableFuture`可以方便地实现异步执行多个任务,并在所有任务完成后进行处理。下面是一个示例代码: ```java import java.util.concurrent.CompletableFuture; public class CompletableFutureExample { public static void main(String[] args) { // 创建多个CompletableFuture对象 CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1"); CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2"); CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> "Task 3"); // 执行所有任务并等待完成 CompletableFuture<Void> allTasks = CompletableFuture.allOf(task1, task2, task3); // 在所有任务完成后进行处理 allTasks.thenRun(() -> { try { // 获取任务的结果 String result1 = task1.get(); String result2 = task2.get(); String result3 = task3.get(); System.out.println("Task 1 result: " + result1); System.out.println("Task 2 result: " + result2); System.out.println("Task 3 result: " + result3); // 继续后续的操作 // ... } catch (Exception e) { e.printStackTrace(); } }); // 等待所有任务完成 allTasks.join(); } } ``` 在上述代码中,我们创建了三个`CompletableFuture`对象:`task1`、`task2`和`task3`,它们代表了三个异步任务。然后,我们使用`CompletableFuture.allOf()`方法将这三个任务组合成一个新的`CompletableFuture`对象`allTasks`,该对象将在所有任务完成后触发。在`allTasks.thenRun()`中,我们定义了所有任务完成后的处理逻辑,包括获取每个任务的结果并进行处理。最后,我们调用`allTasks.join()`方法等待所有任务完成。 使用`CompletableFuture`可以更灵活地处理异步任务的结果和异常,还可以通过方法链的方式组合多个任务
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值