2018年9月

在使用RPC过程中,经常会调用多个RPC服务来获取数据。

比如获取用户个人主页的时候,就要去用户服务获取用户的头像、昵称等基本信息,还要去访问服务获取用户最近访问的信息,还有去关系服务获取用户新增的粉丝或关注的主播的消息。

值得注意的是,这些服务之间并没有依赖,即并不需要先获取用户的头像才能获取用户的访问信息。

如果一个一个地调用这些RPC服务,那么消耗的总时间就是这些RPC调用耗时之和。

因为这些服务之间并没有依赖,所以可以并行地调用,那么消耗的总时间就是耗时最长的那个RPC调用的时间。特别是当调用的RPC服务众多时,并且调用可以大幅度减少时间,提高效率。

如何并行调用呢?

采用线程池和Future就可以,样例如下。
进行两个计算任务,每个需要耗时3秒,如果按照往常调用,那么总共需要6秒时间。但如果并行调用,只需3秒。

import java.time.LocalDateTime;
import java.util.concurrent.*;

public class FutureTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {


        ExecutorService executorService =
                Executors.newFixedThreadPool(4);

        Callable<Integer> calculateA = new SumCalculateTask(3, 4);
        Callable<Integer> calculateB = new SumCalculateTask(4, 6);

        System.out.println("START AT " + LocalDateTime.now());
        Future<Integer> futureA = executorService.submit(calculateA);
        Future<Integer> futureB = executorService.submit(calculateB);

        Integer resultA = futureA.get(4, TimeUnit.SECONDS);
        System.out.println(resultA);
        Integer resultB = futureB.get(4, TimeUnit.SECONDS);
        System.out.println(resultB);

        System.out.println("END AT " + LocalDateTime.now());
        executorService.shutdown();
    }


    static class SumCalculateTask implements Callable<Integer> {

        private Integer a;
        private Integer b;

        public SumCalculateTask(Integer a, Integer b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public Integer call() throws Exception {
            Thread.sleep(3000);
            return a + b;
        }
    }
}

Github源码示例:https://github.com/chengjf/java-snippet/blob/master/src/main/java/com/chengjf/future/ConcurrentCalculatorTest.java