JUC并发编程 CompletableFuture 常用方法 (一)

1 get()

用get()方法来获取线程计算结果的返回值

    @SneakyThrows
    public static void future(){
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName() + "----come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            try {
                TimeUnit.SECONDS.sleep(5);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            return result;
        });
        //不见不散,非要等到结果才会离开,不管你是否计算完成,容易造成程序堵塞
        System.out.println(completableFuture.get());
        System.out.println(Thread.currentThread().getName() + "线程先去忙其它任务");

    }

1 从上述程序中我们可以看出,当我们使用get()方法获取线程的计算结果,必须要等到线程计算完毕,和FutureTask一样,还是阻塞了。
2 get()方法容易阻塞,一般建议放在程序后面,一旦调用不见不散,非要等到结果才会离开,不管你是否计算完成,容易程序堵塞。

2 get(long timeout,TimeUnit unit)

上面get()必须要等到线程计算完,假如我不想等待呢?可以用get(long timeout,TimeUnit unit)方法

    @SneakyThrows
    public static void future1(){
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName() + "----come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            try {
                TimeUnit.SECONDS.sleep(3);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            return result;
        });
        
        System.out.println(completableFuture.get(2,TimeUnit.SECONDS));
        System.out.println(Thread.currentThread().getName() + "线程先去忙其它任务");

    }

3 whenComplete

当线程计算完成时 会回调此方法

@SneakyThrows
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName() + "----come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            try {
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("-----1秒钟后出结果:"+result);
            return result;
        //如果完成 v = result 的返回值  e = exception
        },executorService).whenComplete((v,e)->{
            //如果没有异常
            if(e == null){
                System.out.println("-----计算完成,更新系统UpdateValue: "+v);
            }
        });
        System.out.println(Thread.currentThread().getName() + "线程先去忙其它任务");
        executorService.shutdown();
    }

从上图的执行顺序我们可以看出,当我们获取线程计算的返回值时,并不需要像get()方法那样等到线程执行完毕才往下走,而是线程执行完毕会主动回调,触发whenComplete

4 exceptionally

上面程序执行正常会回调whenComplete方法,那么当程序执行异常呢?会回调exceptionally方法

    @SneakyThrows
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName() + "----come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            try {
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            //模拟异常
            int i = 10/0;
            System.out.println("-----1秒钟后出结果:"+result);
            return result;
        //如果完成 v = result 的返回值  e = exception
        },executorService).whenComplete((v,e)->{
            //如果没有异常
            if(e == null){
                System.out.println("-----计算完成,更新系统UpdateValue: "+v);
            }
        }).exceptionally(e->{
            e.printStackTrace();
            System.out.println("异常情况:"+e.getCause()+"\t"+e.getMessage());
            return null;
        });
        System.out.println(Thread.currentThread().getName() + "线程先去忙其它任务");

        executorService.shutdown();
    }

5 总结

从上面的例子中我们发现,CompletableFuture 不仅有FutureTask中的get() 和 get(long timeout,TimeUnit unit) 方法,还扩展了一些会回调的方法,非常好用,简直是业务代码异步编程神器。

CompletableFuture优点:

  • 异步任务结束时,会自动回调某个对象的方法
  • 主线程设置好回调后,不用关心异步任务的执行,异步任务之间可以顺序执行
  • 异步任务出错时,会自动回调某个对象的方法
posted @ 2024-01-14 14:29  KwFruit  阅读(26)  评论(0编辑  收藏  举报