前言
公司最近项目需要将整个系统进行大批量数据导出,接下来简单说一下实现思路。
多个线程之间是同时执行的,不能保证哪个线程先执行完,但是却要保证数据的一致性,在这里我们可以实现callable接口获取返回值,我们获取到所有子线程的查询结果然后合并到一个结果集中。
保证合并的顺序我们可以这么做:
- 创建一个FutureTask类型的List,该FutureTask的类型就是返回的结果集
- 每启动一个线程,就将该线程的FutureTask添加到tasks列表中
- 顺序赋值,按照顺序从tasks中取出FutureTask,执行FutureTask的get方法,该方法会阻塞调用的线程直到拿到处理结果
话不多说直接贴代码
private List<TtlProductInfoPo> multiThreadListProduct() {
List<FutureTask<List<TtlProductInfoPo>>> tasks = new ArrayList<>();
List<TtlProductInfoPo> productInfoPos = new ArrayList<>();
int totalNum = 500000;
int loopNum = new Double(Math.ceil((double) totalNum / THREAD_MAX_ROW)).intValue();
log.info("多线程查询,总数:{},开启线程数:{}", totalNum, loopNum);
long start = System.currentTimeMillis();
executeTask(tasks, loopNum, totalNum);
for (FutureTask<List<TtlProductInfoPo>> task : tasks) {
try {
productInfoPos.addAll(task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
log.info("查询结束,耗时:{}", System.currentTimeMillis() - start);
return productInfoPos;
}
private void executeTask(List<FutureTask<List<TtlProductInfoPo>>> tasks, int loopNum, int total) {
for (int i = 0; i < loopNum; i++) {
Map<String, Object> map = new HashMap<>();
map.put("offset", i * THREAD_MAX_ROW);
if (i == loopNum - 1) {
map.put("limit", total - THREAD_MAX_ROW * i);
} else {
map.put("limit", THREAD_MAX_ROW);
}
FutureTask<List<TtlProductInfoPo>> task = new FutureTask<>(new listThread(map));
log.info("开始查询第{}条开始的{}条记录", i * THREAD_MAX_ROW, THREAD_MAX_ROW);
new Thread(task).start();
// 将任务添加到tasks列表中
tasks.add(task);
}
}
private class listThread implements Callable<List<TtlProductInfoPo>> {
private Map<String, Object> map;
private listThread(Map<String, Object> map) {
this.map = map;
}
@Override
public List<TtlProductInfoPo> call() {
return listProduct(map);
}
}
总结
分享一下思路和实现方法,欢迎各位批评指正哦。