我先说一下我们公司(某金融公司)的这个需求吧,最近预授信项目要上线了,作为公司实习生的我肯定不能参与核心业务,于是给我分配了这样一个需求。
上传Excel文件,并解析Excel里面的数据,判断userId是否存在,是否存在额度申请,是否存在借款申请,是否存在额度账户,这些都没有的话,判定导入用户有效。 |
1、上传文件,这个简单一些,直接使用公司自己封装的框架,把文件上传到配置文件配置的路径。下载就是反过来,通过前端传来的地址,去dfs拉取文件。
2、解析过程是在提交授信申请的时候触发, 上传的excel可能会出现导入大量用户(破万)的情况,所以如果是单线程同步处理,可能一小时也处理不完。因为解析一次需要的判断逻辑很多,中间调用了很多dubbo接口,网络延迟是必然的。
有两种方案: 一、使用跑批任务定时拉取申请授信的数据,然后异步处理。 二、使用多线程解析Excel
第一种也可以,但是需要改动其他项目的代码,使得系统复杂度增加。
这里使用了第二种 ,代码如下
@Override
public List<Map<String, Integer>> deal(List<Map<Integer, String>> list, String bitchId, String name) {
final int THREAD_NUM = 100;
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUM);
List<Future<Map<String, Integer>>> futures = new ArrayList<>(THREAD_NUM);
List<Map<String, Integer>> maps = new ArrayList<>();
int size = list.size();
for (int i = 0; i < THREAD_NUM; i++) {
List<Map<Integer, String>> subList = (i == THREAD_NUM - 1) ? list.subList(size / THREAD_NUM * i, list.size())
: list.subList(size / THREAD_NUM * i, size / THREAD_NUM * (i + 1));
DealCallable dealCallable = new DealCallable();
dealCallable.setThreadNum(i);
dealCallable.setBitchId(bitchId);
dealCallable.setUserName(name);
dealCallable.setBasPreApprovalService(this);
dealCallable.setList(subList);
futures.add(executorService.submit(dealCallable));
}
for (Future<Map<String, Integer>> future : futures) {
try {
maps.add(future.get());
} catch (Exception e) {
log.info("线程处理错误", e);
}
}
executorService.shutdown();
return maps;
}
DealCallable这个类是自定义的,继承了Callable接口,并且重写了call()方法,返回解析的数据,代码如下
@Data
public class DealCallable implements Callable<Map<String, Integer>> {
private int threadNum;
private String bitchId;
private String userName;
private BasPreApprovalService basPreApprovalService;
private List<Map<Integer, String>> list;
@Override
public Map<String, Integer> call() throws Exception {
return basPreApprovalService.analysis(list, bitchId, userName, threadNum);
}
}