• 多线程拆分list,合并list


    今天有一个接口20s 才能展示出来数据,这怎么可以领导直接让我去处理这个接口,处理不出来就不要下班了

    我心中一紧 赶紧去看这是哪个垃圾写出来的代码

    浏览了一下代码发现  需求是这样子的  后台请求一个地址 返回了一个list集合,我拿着这个list 集合对象的主键,再去调用查看详情接口,拼接到原来的对象上。最后在合并拼接上参数的对象集合。

    以前的兄弟直接for循环调用,数据量不大 130多条数据 但是也需要20秒(1个接口调用150毫秒,帮大家算出来了)。

    这怎么行,祭出大杀器,多线程。

    我们需要用callable 的线程方法  因为我们还需要将返回值 给他拼回去  代码如下  

    package com.zhgw.dev.pioc.utils;
    
    import com.alibaba.fastjson.JSONObject;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CountDownLatch;
    
    public class PersionThread implements Callable {
        /** 数据集合 */
        private List<PersionDTO> list;
        /** 权限  */
        private String token;
    
        /** 每个线程处理的起始数据 */
        private CountDownLatch begin;
        /** 每个线程处理的结束数据 */
        private CountDownLatch end;
    
        public PersionThread() {
        }
    
        public PersionThread(List<PersionDTO> list, CountDownLatch begin, CountDownLatch end,String token) {
            this.list = list;
            this.begin = begin;
            this.end = end;
            this.token = token;
        }
        @Override
        public  List<PersionDTO> call() throws Exception {
            try {
                if (list != null && !list.isEmpty()) {
                    //  testBatchInsertMapper.batchInsert(list);
                    List<PersionDTO> PersionDTOArrayList = new ArrayList<>();
                    int size = list.size();
                    for (PersionDTO PersionDTO :list) {
                        String personString = HttpUtils.httpPostForm("http://www.baidu.com" + "?token=" + token + "&oid=" + PersionDTO.getInspectoroid(), null, false, "160");
                        
                    }
                    //System.out.println("线程"+JSONObject.toJSONString(PersionDTOArrayList));
                    return PersionDTOArrayList;
                }
                // 执行完让线程直接进入等待
                begin.await();
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 当一个线程执行完 了计数要减一不然这个线程会被一直挂起
                end.countDown();
            }
            return null;
        }
    
    }

    执行多线程的方法

    public  List batchInsertByThread(List<PersionDTO> list, String token){
    
            if (list == null || list.isEmpty()) {
                return null;
            }
            // 一个线程处理6条数据
            int count = 7;
            // 数据集合大小
            int listSize = list.size();
            // 开启的线程数
            int runSize = (listSize / count) + 1;
            // 存放每个线程的执行数据
            List<PersionDTO> newList = null;
            // 创建一个线程池,数量和开启线程的数量一样
            ExecutorService executor = Executors.newFixedThreadPool(runSize);
            // 创建两个个计数器
            CountDownLatch begin = new CountDownLatch(1);
            CountDownLatch end = new CountDownLatch(runSize);
            List<Future< List<PersionDTO>>> futures = new ArrayList<Future< List<PersionDTO>>>();
            // 创建一个存储所有返回值的list
            List<PersionDTO> listAll = Collections.synchronizedList(new ArrayList<PersionDTO>());
    
            for (int i = 0; i < runSize; i++) {
                /* 计算每个线程执行的数据 */
                if ((i + 1) == runSize) {
                    int startIdx = (i * count);
                    int endIdx = list.size();
                    newList = list.subList(startIdx, endIdx);
                } else {
                    int startIdx = (i * count);
                    int endIdx = (i + 1) * count;
                    newList = list.subList(startIdx, endIdx);
                }
                PersionThread PersionThread = new PersionThread(newList, begin, end, token);
                futures.add(executor.submit(PersionThread));
            }
            begin.countDown();
            //System.out.println("submit"+ JSONObject.toJSONString(submit));
            try {
                for(Future< List<PersionDTO>> future : futures){
                    //合并操作
                    List<PersionDTO> PersionDTOS = null;
                    try {
                        PersionDTOS = future.get();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                    listAll.addAll(PersionDTOS);
                }
                //System.out.println(JSONObject.toJSONString(listAll));
                end.await();
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            executor.shutdown();
            return listAll;
        }

    调用线程的方法

    public static void main(String[] args) {
            R<List<PersonnelGPSDTO>> listR = personnelGPS();
            System.out.println(listR);
  • 相关阅读:
    if、else if 、else及switch...case使用小记(C#)
    c#基础知识
    流与文本文件操作(C#)
    .NET中的异常处理机制(一)
    .NET中的异常处理机制(二)
    在引用类型变量上调用虚方法和非虚方法的区别
    各位客官!鼠标点击一个Button之后究竟发生了什么?您知道么?(C#)
    接口和抽象类的使用场景以及多类继承存在的问题(c#)
    面向对象SOLID设计原则之Open-Closed原则
    stack和stack frame
  • 原文地址:https://www.cnblogs.com/dupeilin/p/14247553.html
Copyright © 2020-2023  润新知