线程池实战——callable线程同步拉取账单信息并入库

近期开发任务中,有一个需求是拉取其他多个的接口的数据存入到表单中; 并且多个接口之间并没有什么太大的关联性, 并且没有顺序要求, 考虑使用线程池去处理这样任务. 且由于数据量较大, 考虑使用callable线程去并发拉取数据, 获取数据后再进行处理


1. 线程池

1.1 引入线程池的目的

我们知道,创建和销毁线程是一件十分损耗内存资源的, 在一个应用程序中,如果需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而在Java开发体系中,内存资源是及其宝贵的,所以,我们就提出了线程池的概念. 更具体点的解释是Java中开辟出的一种管理线程的概念,这个概念叫做线程池,从概念以及应用场景中,我们可以看出,线程池的好处,就是可以 方便的管理线程,也可以减少内存的消耗

1.2 四种常用的线程池

  • CachedThreadPool: 可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于 耗时少,任务量大的情况
  • SecudleThreadPool: 周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务
  • SingleThreadPool: 只有一条线程来执行任务,适用于有顺序的任务的应用场景。
  • FixedThreadPool: 定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程。

2. Callable线程和FutureTask组装数据

Callable是创建多线程的方式之一, 它可以有返回值,也可以抛出异常的特性;
FutureTask是一个可取消的异步计算。FutureTask提供了对Future的基本实现,可以调用方法去开始和取消一个计算,可以查询计算是否完成并且获取计算结果;

一个简单的demo展示:

   FutureTask futureTask=new FutureTask(new Callable() {
      @Override
        public String call() throws Exception {
            Thread.sleep(3000);
            System.out.println("calld方法执行了");
            return "call方法返回值";
        }
    });
    futureTask.run();
    System.out.println("获取返回值: " + futureTask.get());
    FutureTask futureTask1=new FutureTask(new Callable() {
        @Override
        public String call() throws Exception {
            Thread.sleep(3000);
            System.out.println("calld方法执行了1");
            return "call方法返回值1";
        }
    });
    futureTask1.run();
    System.out.println("获取返回值1: " + futureTask1.get());

在上述的需求当中,由于接口拉取数据是没有先后关系的, 我们可以单独去通过线程池创建多个callable线程, 并通过FutureTask获取异步线程拉取到的数据并组装数据.


3. 实战

ExecutorService executorService = Executors.newCachedThreadPool();
    CompletionService<Map<String, String>> cs = new ExecutorCompletionService<>(executorService);
    Callable compareCallable = () -> getCompareInfo(request);
    
    Callable getDeptInfoCallable = () -> getDeptInfo(request);
    
    Callable getPaymentDetailInfoCallable = () -> getPaymentDetailInfo(request);
    
    Callable getAllowanceDetailCallable = () -> getAllowanceDetail(request);
    //构建futureTask任务,控制返回顺序
    FutureTask<Map<String, String>> futureTask1 = new FutureTask<Map<String, String>>(compareCallable);
    FutureTask<Map<String, String>> futureTask2 = new FutureTask<Map<String, String>>(getDeptInfoCallable);
    FutureTask<Map<String, String>> futureTask3 = new FutureTask<Map<String, String>>(getPaymentDetailInfoCallable);
    FutureTask<Map<String, String>> futureTask4 = new FutureTask<Map<String, String>>(getAllowanceDetailCallable);
    StopWatch sw = new StopWatch("差旅对账接口调用耗时");
    sw.start("对比信息");
    executorService.submit(futureTask1);
    sw.stop();
    sw.start("账单汇总");
    executorService.submit(futureTask2);
    sw.stop();
    sw.start("账单明细");
    executorService.submit(futureTask3);
    sw.stop();
    sw.start("差补明细");
    executorService.submit(futureTask4);
    sw.stop();
    log.info("差旅对账接口调用耗时汇总" + sw.prettyPrint());
    //获取对比信息
    String compareResult = (futureTask1.get()).get("compareResult");
    //获取差补行程信息
    String orderSettlementDetailJson = (futureTask3.get()).get("orderSettlementDetailJson");
    //获取补贴数据
    String allowanceDetailJson = (futureTask4.get()).get("allowanceDetailJson");
    Map<String, String> temp = futureTask2.get();
    String allowanceSummaryRes = temp.get("allowanceSummaryRes");
    String snapshotInfoRes = temp.get("snapshotInfoRes");
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容