zoukankan      html  css  js  c++  java
  • Future and CompletableFuture

    Future代表异步执行的结果,也就是说异步执行完毕后,结果保存在Future里, 我们在使用线程池submit()时需要传入Callable接口,线程池的返回值为一个Future,而Future则保存了执行的结果 ,可通过Future的get()方法取出结果,如果线程池使用的是execute(),则传入的是Runnable接口 无返回值。

        /**
         * submit返回值为Future,
         * @param num
         * @return
         */
        public static Future<?> futureTask(Integer num) {
            return executorService.submit(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    return getMemberStatusRpcApi(num);
                }
            });
        }
    
         /**
         * execute无返回值,因为参数是Runnable
         */
        public static void noResult(Integer num){
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    getMemberStatusRpcApi(num);
                }
            });
        }

    获取异步执行结果使用get(),isDone判断异步执行是否结束

     Future<?> future = futureTask(20);
       if (future.isDone()){
          System.out.println(future.get());
       }

    cancel(),取消异步执行

     Future<?> future = futureTask(20);
     future.cancel(true);

    get(long time , TimeUnit time),在指定时间内获取执行结果,如果超过时间还没获取到结果,则报超时异常

      Future<?> future = futureTask(20);
      future.get(3,TimeUnit.SECONDS);

    isCancelled(),判断任务是否取消

      boolean cancelled = future.isCancelled();

    execute()和submit区别

    1.execute无返回值,这样就无法知道任务是否执行成功 2.execute抛出异常后无法处理,不能捕捉异常,而submit可以捕获异常;

    Future不足之处

    虽然Future在执行多个操作时的确做到了异步,但是Future.get()取出异步执行结果的时候缺是阻塞的, 只有当前一个操作get完以后才能到下一个操作get 

    CompletableFuture

    1:当我们系统中某个接口需要调用多个接口,如果我们使用同步的方式去调用,那么只有等一个接口调用完毕后再到下一个接口继续调用,如果这些任务不耗时,其实是完全能接受的,但是如果调用的这些接口耗时,用同步的方式去调用其实是不明智的做法。 如图,我们系统需要用RPC远程去调用A,B,C,D四个系统的接口,每个接口耗时100ms,那么总共就是400ms 

    我们能不能想其它的方法来缩短时间呢?当然可以,譬如使用消息队列,在这里我们先不讨论中间件,而是直接使用java类库,Java8引入了CompletableFuture,使用它可以进行完美的异步操作,我们看下使用它后的示意图。 可以看出,使用CompletableFuture是异步调用的,等到大家都调用结束后,再对结果进行汇总 

    code

    private static CompletableFuture<Integer> test1() throws InterruptedException {
            return CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 1;
            });
        }
    
        private static CompletableFuture<Integer> test2() throws InterruptedException {
    
            return CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 2;
            });
        }
    
        private static CompletableFuture<Integer> test3() throws InterruptedException {
            return CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 3;
            });
        }
        
        /**
         *如下代码,我们要计算三个接口的返回值进行汇总,每个接口耗时两秒,同步执行
         *需要消耗6秒,使用Completable后只需要2秒, anyOff是将多个执行完毕的
         *CompletableFuture进行计算
         *
         */
        private static CompletableFuture<Integer> solution() throws InterruptedException {
            CompletableFuture<Integer> test1 = test1();
            CompletableFuture<Integer> test2 = test2();
            CompletableFuture<Integer> test3 = test3();
            return CompletableFuture
                    .anyOf(test1,test2,test3)
                    .thenApply(v -> {
                        Integer i = 0;
                        try {
                            Integer integer = test1.get();
                            Integer integer1 = test2.get();
                            Integer integer2 = test3.get();
                            i = integer + integer1 + integer2;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (ExecutionException e) {
                            e.printStackTrace();
                        }
                        return i;
                    });
        }
     
    生命不止,折腾不息
  • 相关阅读:
    python制作一个塔防射箭游戏
    有两个链表a和b,设结点中包含学号、姓名。从a链表中删去与b链表中有相同 学号的那些结点。
    python实现一个简单的21点游戏
    C语音,函数padd的功能是调整pa指向的链表中结点的位置,使得所有x值为偶数的结点出现在链表的前半部,所有x值为奇数的结点出现在链表的后半部。
    scratch绘制特殊图形1
    验证哥德巴赫猜想,输出6-100之间的偶数等于两个质数之和
    写一函数check检测字符串中的左右括号数是否匹配
    C语言文件操作题,将整数1-10及其算术平方根存入文件,再读取出来显示在屏幕上
    湖南2020对口计算机32题第1、2、3小题
    基础
  • 原文地址:https://www.cnblogs.com/steakliu/p/15228457.html
Copyright © 2011-2022 走看看