java-线程池异步获取多平台接口返回结果

业务场景:

公司需要集成多个系统的待办任务数据,将其整合在我们常用的OA系统上展示,这样就不用登录每个系统去查看自己每天的待办任务有哪些。

原有思路:

按照同步的方式,逐一调取每个系统提供的待办接口,获取结果,最后整合汇总。

出现的问题:

随着对接系统的增加,网页刷新出内容的速度会越来越慢,甚至接口超时。

解决方案:

使用线程池,多线程同时调用各系统接口。

代码如下:

 System1.java

public class System1 implements Callable<List<Result>> {
    String params1 = "";
    String url1 = "";

    public System1(String params1, String url1) {  // 通过构造函数,传入不同的请求参数和请求地址
        this.params1 = params1;
        this.url1 = url1;
    }

    @Override
    public List<Result> call() throws Exception {
        System.out.println("begin-----" + Thread.currentThread().getName() + "-----" + new Date() + " system1()");

        List<Result> res = new ArrayList<>();
        /**
         * 这里可以写调取各系统接口,并获取返回结果,封装至res内的逻辑
         */
        Thread.sleep(5000);  // 为体现出异步效果,加入延时5s的逻辑;实际业务中删除即可

        System.out.println("end-----" + Thread.currentThread().getName() + "-----" + new Date() + " system1()");

        return res;
    }
}

 

System2.java

public class System2 implements Callable<List<Result>> {
    String params2 = "";
    String url2 = "";

    public System2(String params2, String url2) {
        this.params2 = params2;
        this.url2 = url2;
    }

    @Override
    public List<Result> call() throws Exception {
        System.out.println("begin-----" + Thread.currentThread().getName() + "-----" + new Date() + " system2()");
        List<Result> res = new ArrayList<>();
        /**
         * 调取其他系统接口,并获取返回结果,封装至res内的逻辑
         */
        Thread.sleep(5000);  // 为体现出异步效果,加入延时5s的逻辑;实际业务中删除即可
        System.out.println("end-----" + Thread.currentThread().getName() + "-----" + new Date() + " system2()");
        return res;
    }
}

 

SystemAll.java

public class SystemAll {

    public List<Result> getAllResult() {
        LocalDateTime beginTime = LocalDateTime.now();
        // 配置线程池:核心线程数量:5;最大线程数:10;空余线程存活时长:1s;存储等待执行任务的队列长度:100;任务拒绝策略:CallerRunsPolicy
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.CallerRunsPolicy());

        List<Callable<List<Result>>> callableList = new ArrayList<>();  // 线程列表
        List<Future<List<Result>>> futureList = new ArrayList<>();  // 线程返回结果列表
        List<Result> res = new ArrayList<>();  // 汇总结果

        callableList.add(new System1("params1", "url1"));  // 单个线程执行类:调取system1系统接口
        callableList.add(new System2("params2", "url2"));

        for (Callable<List<Result>> callableItem : callableList) {
            Future<List<Result>> submitRes = executor.submit(callableItem);  // 提交单个线程至线程池
            futureList.add(submitRes);
//            res.addAll(submitRes.get());  // 不要在此处通过submitRes.get()方法获取结果,会导致线程等待,非异步执行
        }

        for (Future<List<Result>> futureItem : futureList) {
            List<Result> resultItem = new ArrayList<>();
            try {
                resultItem = futureItem.get();  // 获取各个线程的返回结果
            } catch (Exception e) {
                executor.shutdown();
                e.printStackTrace();
            }
            res.addAll(resultItem);
        }

        executor.shutdown();  // 关闭线程池,不再接受新任务;但队列里的任务会执行完毕

        while (executor.isTerminated()) {  // 调用shutdown()后,所有提交的任务完成后,返回true;
            System.out.println(res);
            System.out.println(res.size());
            break;
        }

//        while (!executor.isTerminated()) {}  // 更简洁的写法

        Long timeConsuming = Duration.between(beginTime, LocalDateTime.now()).toMillis();
        System.out.println("时间消耗:" + timeConsuming);

        return res;
    }


    public static void main(String[] args) {
        new SystemAll().getAllResult();
    }
}

 

运行打印结果:

 可以看出:两个系统均需要耗时5s得到返回结果,因开启多线程执行,最终总耗时也只是5s;随着对接系统的增加,异步实现的效率提升效果更加明显。

 

posted @ 2024-12-10 16:26  DoubleFishes  阅读(23)  评论(0编辑  收藏  举报