多线程处理大数据量查询 Published on Apr 3, 2024 in 随笔 with 0 comment 最近在实现一个导入功能,数据量在5w左右,后续会持续增长,使用的是easyExcel,读取文件性能较好,但因为每条数据都要做复杂的数据校验,导致整体响应时间在三四十分钟,虽然说导入不是直接和用户交互,但现在数据量不算很大的情况下,这个响应时间还是需要优化的,读取文件速度在几秒以内,主要是在数据校验这块,所以就使用了多线程去工作。 主要代码: ```java import java.util.concurrent.*; public class Test{ private static final int threadNum = Runtime.getRuntime().availableProcessors()*2;// 获取cpu核数 public void syncData(List regionList) throws ExecutionException, InterruptedException { /** * 多线程分析数据 */ List list = new ArrayList<>(); ExecutorService executor = Executors.newFixedThreadPool(threadNum); int num = (regionList.size() / threadNum) + 1; //计算每个线程需要处理的记录数 for (int j = 0; j < threadNum; j++) { //读取数据的起始位置 int startNum = j * num; //读取数据的结束位置 int endNum = startNum + num; //添加任务 Callable task = new ThredQuery(regionList, startNum, endNum); Future f = executor.submit(task); //接受返回结果 list.add(f); } // 关闭线程池 executor.shutdown(); for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println(f.get().toString()); //OPTION + return 抛异常 } newRegionMapper.save(regionList); log.info("共导入数据 {} 行", regionList.size()); } class ThredQuery implements Callable { private List regionList; private int startNum; private int endNum; public ThredQuery(List regionList, int startNum, int endNum) { this.regionList = regionList; this.startNum = startNum; this.endNum = endNum; //System.out.println(startNum + "\t" + endNum); } @Override public String call() { for (int i = startNum; i < endNum; i++) { //自己的业务逻辑 //if (i < regionList.size()) { //} } return "成功"; } } } ``` 思路: 1:先计算出查询总量,根据服务器的cpu核数,求每个线程应处理的条数 2.使用Callable返回结果,然后聚合数据,最后处理。 这里有个问题就是线程池合理的线程数你是如何考虑的?这也是之前面试遇到的一个题: 1.先看下机器的CPU核数,然后在设定具体参数: System.out.println(Runtime.getRuntime().availableProcessors()); 即CPU核数 = Runtime.getRuntime().availableProcessors() 2.分析下线程池处理的程序是CPU密集型,还是IO密集型 CPU密集型:核心线程数 = CPU核数 + 1 IO密集型:核心线程数 = CPU核数 * 2 本文由 admin 创作,采用 知识共享署名4.0 国际许可协议进行许可。本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。