CompletableFuture异步任务编排

业务场景:

查询详情页的逻辑比较多,有些数据还需要远程调用,必然要花费更多的时间。

1、获取SKU的基本信息 0.5s

2、获取SKU的图片信息 0.5s

3、获取SKU的促销信息 1s

4、获取SPU的所有销售属性 1s

5、获取SPU的详情 1.5s

假如商品详情页的每个查询,如果如上标注的时间才能完成,那么用户需要4.5秒的时间,才能够看到商品详情页面的内容,很显然是不能够接受的。

如果有多个线程同时完成这6步操作,也许仅仅1.5秒就能够完成。

4 5 需要1的返回结果。

completableFuture简单调用

1、简单调用

 //测试异步任务
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main .... start");
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        }, pool);

        System.out.println("main ... end");
    }

 

2、runAsync

没有返回结果的方法调用:

 

3、supplyAsync

有返回结果的方法调用:无论是否get操作,使用了改操作,就是阻塞式等待。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, pool);
        System.out.println(future.get());

 返回结果:

 

可以理解为多线程同步调用。get方法为阻塞式等待。

完成时的回调方法

1、whenComplete

 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, pool).whenComplete((result,exception)->{
            System.out.println("继续上一个线程的执行结果,用同一个线程继续执行");
            System.out.println("result="+result);
            System.out.println("exception="+exception);
        }).exceptionally(excep->{
            return 10; //遭遇到异常的返回结果
        });
        System.out.println(future.get());
        System.out.println("main ... end");

 执行结果:

如果,i=10/0的执行结果如下:

2、exceptionally

总结:

使用whenComplete的回调方法,参数一:返回结果;参数二:异常。但是该方法无法修改返回结果。是执行当前任务的线程继续执行回调方法的任务。

whenCompleteAsync:是执行把whenCompleteAsync这个任务继续提交给线程池来进行执行。

方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行。(如果是使用相同的线程池,也可能会被同一个线程选中执行)

使用exceptionally,如果遭遇到异常,可以修改返回结果的值。

3、handle方法完成后的处理

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果:" + i);
            return i;
        }, pool).handle((result,exception)->{
            if(result!=null){
                return result;
            }
            if(exception!=null){
                return 0;
            }
            return 0;
        });

 执行结果:

 

4、线程串行化方法

thenRunAsync:

不得到上一步的返回结果,直接异步执行任务。

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果:" + i);
            return i;
        }, pool).thenRunAsync(()->{
            System.out.println("哈哈");
        },pool);

 注意:此时,i=10/0 肯定是抛出异常了,但是咱们抛出了异常,所以程序中断;

 如果修改异常代码,i=10/2;

如果使用了thenRun,则是用该线程继续执行任务。

 

thenAcceptAsync:

 

 得到上一步的返回结果,但是新任务结果不返回。

 

 CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, pool).thenAccept(res->{
            System.out.println("res="+res); 
        });

 执行结果:

thenApplyAsync:

 

得到上一步的返回结果,并且返回新任务的结果。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
            return i;
        }, pool).thenApplyAsync(res -> {
            System.out.println("res=" + res);
            return 8;
        }, pool);
        System.out.println("get===="+future.get());
        System.out.println("main ... end");

 

 执行结果:

 

两个任务组合,都要完成

两个任务都完成以后,触发一个事件

thenCombine:

组合两个future,获取两个future的返回结果,并返回当前任务的返回值;

thenAcceptBoth:

组合两个future,获取两个future的返回结果,然后处理任务,没有返回值;

runAfterBoth:组合两个future,不需要获取future的返回结果,只需要两个future处理任务完成后,处理该任务。

CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程1的ID:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程1结束:返回结果为" + i);
            return i;
        }, pool);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程2的ID:" + Thread.currentThread().getId());
            return "线程2结束";
        }, pool);
        
        //Async加上就是异步,到最后执行;不加就是约等于同步
        future01.runAfterBothAsync(future02,()->{
            System.out.println("runAfterBoth:"+"不要线程1和线程2的返回结果,新开一个独立线程运行,不是在线程池中"); 
        });

 

future01.thenAcceptBothAsync(future02, (res1, res2) -> {
            System.out.println("thenAcceptBothAsync:" + "会获取到线程1和线程2的返回结果,res1=" + res1 + ",res2=" + res2 + ",但是新任务不会返回!");
        }, pool);

 

 

 

     CompletableFuture<Object> future = future01.thenCombineAsync(future02, (res1, res2) -> {
            return res1+"----"+res2;
        }, pool);
        System.out.println(future.get().toString());
        System.out.println("main ... end");

 执行结果:

 

两个任务组合,一个完成

当两个任务中,任意一个future任务完成的时候,执行该任务。

applyToEither:两个任务有一个任务执行完成,获取它的返回值,处理任务并有新的返回值。

acceptEither:两个任务有一个任务执行完成,获取它的返回值,处理任务,没有返回值。

runAfterEither:两个任务有一个任务执行完成,不需要获取它的返回值,处理任务,并且没有返回值。

 

多任务组合

allOf:等待所有任务完成

anyOf:只要有一个任务完成

        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();
        System.out.println("main ... end");

 

执行结果:

如果不加线程池,主线程结束,其余线程也会结束掉。其余线程就不打印东西了。所以要想清楚的看到结果,将线程执行放入到线程池中。  

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值