项目中遇到了需要一次性查询大量数据的情况,使用多线程并发查询。 原理是多个线程进行分页查询再将查询结果合并取出。
一、实现分页插件
/*** * 分页插件 */public class Paging { public static List returnList(int page ,int limit,List mList){ int pageSize=limit;//每页显示数据 int pageNo=page;//页码 pageNo=(pageNo-1)*pageSize; //每页的起始索引 Integer sum = mList.size(); //记录总数 if(sum!=0) { if (pageNo+pageSize > sum) { mList = mList.subList(pageNo,sum); }else { mList = mList.subList(pageNo,pageNo+pageSize); } } return mList; }}实现分页
二、按需数据量进行开启合理的线程数据查询数据库,一同进行返回
/***模拟数据库数据的情况*/private static Map map=new HashMap<>();static { map.put("111","aaa"); map.put("222","bbb"); map.put("333","ccc"); map.put("444","ddd");}public static void getData(List telePhone){ //假如每次限定访问的数据量为2,此处为模拟数据 int limit=2; //限定开启访问的线程数据大概多少 int count=telePhone.size()%limit==0?telePhone.size()/limit:telePhone.size()/limit+1; List>> futureTasks=new ArrayList<>(); //进行遍历请求 for (int i=1;i<=count;i++){ List tmpTelePhone=Paging.returnList(i,limit,telePhone); //使用具有返回值的callable FutureTask> futureTask=new FutureTask<>((Callable)()->{ log.info("查询数据"); //此处模拟的是请求数据库 List stringList=new ArrayList<>(); tmpTelePhone.stream().forEach(t-> stringList.add(map.get(t))); return stringList; }); log.info("执行开启线程-"+i); futureTasks.add(futureTask); Thread thread=new Thread(futureTask); thread.setName("thread-"+i); thread.start(); } List stringList=new ArrayList<>(); futureTasks.forEach(obj -> { try { //获取返回的数据,进行保存到集合中 stringList.addAll(obj.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }); //综合请求返回的结果 System.out.println(stringList);}
模拟请求数据库
分批进行请求数据库
获取返回的结果
三、结果返回
20:23:18.987 [main] INFO xxx.xxx.xxx.utils.xxx.xxx - 执行开启线程120:23:18.990 [main] INFO xxx.xxx.xxx.utils.xxx.xxx - 执行开启线程220:23:18.990 [thread-1] INFO xxx.xxx.xxx.utils.xxx.xxx - 查询数据20:23:18.993 [thread-2] INFO xxx.xxx.xxx.utils.xxx.xxx - 查询数据[aaa, bbb, ccc, ddd]Process finished with exit code 0 | 留言与评论(共有 0 条评论) “” |