java8 -- 异步编程

一:创建任务并执行任务

1:无参创建:CompletableFuture<String> noArgsFuture = new CompletableFuture<>();

2:传入相应任务,无返回值(runAsync方法可以在后台执行异步计算,但是此时并没有返回值。持有一个Runnable对象。)

CompletableFuture noReturn = CompletableFuture.runAsync(()->{
    //执行逻辑,无返回值
});

3:传入相应任务,有返回值;(此时我们看到返回的是CompletableFuture<T>此处的T就是你想要的返回值的类型。其中的Supplier<T>是一个简单的函数式接口。)

CompletableFuture<String> hasReturn = CompletableFuture.supplyAsync(new Supplier<String>() {
    @Override
    public String get() {
        return "hasReturn";
    }
});

         此时可以使用lambda表达式使上面的逻辑更加清晰:get方法获取返回结果

CompletableFuture<String> hasReturnLambda = CompletableFuture.supplyAsync(TestFuture::get);

 3:获取返回值(异步任务也是有返回值的,当我们想要用到异步任务的返回值时,我们可以调用CompletableFutureget()阻塞,直到有异步任务执行完有返回值才往下执行)

4:自定义返回值(我们也可以在任意时候调用complete()方法来自定义返回值)

CompletableFuture<String> future1 = new CompletableFuture<>();
        System.out.println("main method is invoking");
        try {
            new Thread(()->{
                System.out.println("thread is invoking");
                try {
                    Thread.sleep(5000);
                    future1.complete("123456");
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("thread is end");


            }).run();
            System.out.println("Main Method End value is " + future1.get());
        }catch (Exception e){
            e.printStackTrace();
        }

 

二:按顺序执行异步任务

如果有一个异步任务的完成需要依赖前一个异步任务的完成,那么该如何写呢?是调用get()方法获得返回值以后然后再执行吗?这样写有些麻烦,CompletableFuture为我们提供了方法来完成我们想要顺序执行一些异步任务的需求。thenApplythenAcceptthenRun这三个方法。这三个方法的区别就是。

一般来说thenAcceptthenRun这两个方法在调用链的最末端使用。实例如下: 

 // thenApply  可获取前一个任务的返回值,自身也有返回值
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "one");
        CompletableFuture<String> future2 = future1.thenApply(name -> name + "two");
        try{
            System.out.println(future2.get());
        }catch (Exception e){
            e.printStackTrace();
        }


        // thenAccept 可获取前一个任务的返回值,但是自身没有返回值
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "three");
        future3.thenAccept(name -> System.out.println(name + "thenAccept"));
        System.out.println("----------------------");

        try{
            System.out.println(future3.get());
        }catch (Exception e){
            e.printStackTrace();
        }

        //thenRun 获取不到前一个任务的返回值,也无返回值
        System.out.println("-------------");
        CompletableFuture<Void> thenRun = future3.thenRun(() -> {
            System.out.println("thenRun");
        });
        try{
            System.out.println(thenRun.get());
        }catch (Exception e){
            e.printStackTrace();
        }

1:thenApply和thenApplyAsync的区别 

如果使用thenApplyAsync,那么执行的线程是从ForkJoinPool.commonPool()中获取不同的线程进行执行,如果使用thenApply,如果supplyAsync方法执行速度特别快,那么thenApply任务就是主线程进行执行,如果执行特别慢的话就是和supplyAsync执行线程一样。接下来我们通过例子来看一下,使用sleep方法来反应supplyAsync执行速度的快慢。

//thenApply和thenApplyAsync的区别
System.out.println("-------------");
CompletableFuture<String> supplyAsyncWithSleep = CompletableFuture.supplyAsync(()->{
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "supplyAsyncWithSleep Thread Id : " + Thread.currentThread();
});
CompletableFuture<String> thenApply = supplyAsyncWithSleep
        .thenApply(name -> name + "------thenApply Thread Id : " + Thread.currentThread());
CompletableFuture<String> thenApplyAsync = supplyAsyncWithSleep
        .thenApplyAsync(name -> name + "------thenApplyAsync Thread Id : " + Thread.currentThread());
System.out.println("Main Thread Id: "+ Thread.currentThread());
System.out.println(thenApply.get());
System.out.println(thenApplyAsync.get());
System.out.println("-------------No Sleep");
CompletableFuture<String> supplyAsyncNoSleep = CompletableFuture.supplyAsync(()->{
    return "supplyAsyncNoSleep Thread Id : " + Thread.currentThread();
});
CompletableFuture<String> thenApplyNoSleep = supplyAsyncNoSleep
        .thenApply(name -> name + "------thenApply Thread Id : " + Thread.currentThread());
CompletableFuture<String> thenApplyAsyncNoSleep = supplyAsyncNoSleep
        .thenApplyAsync(name -> name + "------thenApplyAsync Thread Id : " + Thread.currentThread());
System.out.println("Main Thread Id: "+ Thread.currentThread());
System.out.println(thenApplyNoSleep.get());
System.out.println(thenApplyAsyncNoSleep.get());

三:组合CompletableFuture 

 将两个CompletableFuture组合在一起有两个方法:

  1. thenCompose():当第一个任务完成时才会执行第二个操作
  2. thenCombine():两个异步任务全部完成时才会执行某些操作

 thenCompose() 用法:

定义两个异步任务,假设第二个定时任务需要用到第一个定时任务的返回值。

public static CompletableFuture<String> getTastOne(){
    return CompletableFuture.supplyAsync(()-> "topOne");
}

public static CompletableFuture<String> getTastTwo(String s){
    return CompletableFuture.supplyAsync(()-> s + "  topTwo");
}

利用thenCompose()方法进行编写

CompletableFuture<String> thenComposeComplet = getTastOne().thenCompose(s -> getTastTwo(s));
System.out.println(thenComposeComplet.get());

// 输出: topOne  topTwo

thenCombine() 用法:

例如我们此时需要计算两个异步方法返回值的和。求和这个操作是必须是两个异步方法得出来值的情况下才能进行计算,因此我们可以用thenCombine()方法进行计算。

CompletableFuture<Integer> thenComposeOne = CompletableFuture.supplyAsync(() -> 192);
CompletableFuture<Integer> thenComposeTwo = CompletableFuture.supplyAsync(() -> 196);
CompletableFuture<Integer> thenComposeCount = thenComposeOne
        .thenCombine(thenComposeTwo, (s, y) -> s + y);
System.out.println(thenComposeCount.get());

此时thenComposeOnethenComposeTwo都完成时才会调用传给thenCombine方法的回调函数。 

 

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值