集群多线程设计
为了加快执行速度,使得设计集群内机器开启多线程执行,执行数据。
1) 发起服务的机器称为主服务器,首先主服务器获取需要处理数据的最大最小ID,以及获取需要参与处理的集群节点服务器IP
2) 将该批数据均匀分布给参与处理的机器节点,每台机器获取到需要处理的该批次数据段最大最小ID
3) 使用Redis消息机制,发布消息,集群下机器订阅到消息,而获取到消息的机器判断自己是否需要参与处理
4) 需要参与处理的机器获取需要处理的数据量,以及每个线程处理数据大小和开启线程大小,分页获取该次要处理的数据
5) 将分页获取该次要处理的数据等参数传输给多线程程序,从线程池内取出线程开启多线程进行处理
6) 节点机器获取线程处理结果,通过消息发送出去,主服务器订阅处理结果,当主服务器获取所有节点结果,将结果反馈出去,执行完成;
/** * 按服务器平分集合 * @param oneSize 每次数据量 * @param list 总的list * @return */ public Map<Integer,List<T>> splitList(Integer oneSize, List<T> list){ Map<Integer,List<T>> map = new HashMap<>(); //数量小于线程数 if(oneSize>=list.size()){ map.put(0,list); return map; } int totalSize = list.size(); //总数据量 int one = totalSize%oneSize==0?0:1; int poolSize = totalSize / oneSize+one; //总线程数 for (int i = 0; i < poolSize; i++) { int sizeEnd = (i+1)*oneSize; if(sizeEnd>totalSize){ sizeEnd=totalSize; } List<T> value = list.subList(i * oneSize, sizeEnd); map.put(i,value); } return map; } |
开启多线程核心代码:
public List<Map<String,Object>> executeCallable(Integer poolSize,Integer number, List<T> listData, String code) { // 等待线程返回所有结果 List<Map<String,Object>> finalist = new ArrayList<>(); int totalSize = listData.size(); //总数据量 int sizeOne =poolSize*number; //一次传输的数据量 int one = totalSize%sizeOne==0?0:1; int sizeFor = totalSize/sizeOne+one; //需要调用循环次数 for(int j=0;j<sizeFor;j++){ int sizeEnd = (j+1)*sizeOne; if(sizeEnd>=totalSize){ sizeEnd=totalSize; } List<T> datas = listData.subList(j*sizeOne,sizeEnd); List<Future<Map<String,Object>>> futureList = new ArrayList<>(); Map<Integer,List<T>> map = splitList(number,datas); // 根据map大小开启对应的线程数量 for (int i=0;i<map.size();i++) { // 开启线程 final int finalI = i; List<T> list = map.get(finalI); Callable<Map<String,Object>> task = new Callable() { @Override public Map<String,Object> call() throws Exception { logger.info("线程"+finalI+"的集合大小:"+map.get(finalI).size()); // 业务逻辑代码 switch (code){ case "XXX":{ //XXX return } } return null; } };
Future<Map<String,Object>> future = threadPoolTaskExecutor.submit(task); //任务提交到线程池并启动 futureList.add(future); } for(Future<Map<String,Object>> future:futureList) { Map<String,Object> mapOne=null; try { mapOne = future.get(); // 等待future对应的线程执行结束 } catch(Exception e) { logger.error(e.getMessage()); mapOne = new HashedMap(); mapOne.put(RETURN_CODE,"E"); mapOne.put(RETURN_MESSAGE,e.getMessage()); e.printStackTrace(); }finally { finalist.add(mapOne); } } logger.info("最终集合大小:" + finalist.size()); } return finalist; } |