1.多线程的导入导出excel。
前一个月中,工作中遇到了一个导出数据库中学生的作业,运维人员反馈很慢,特别是数据量比较大的时候,所以后台就进行了多线程分页导出excel
解决方案:用分页和多线程的思想解决
主要代码如下:
线程的callback方法,就是执行的线程方法体
/**
* Created by zhang
* Date:2019/02/26
* 调用方法查询数据
*/
class Task implements Callable<List<AwbInfo>> {
Integer start;
Integer end;
List<String> fields;
List<Where> wheres;
List<Order> orders;
UserAccount account;
Task(Integer start, Integer end, List<String> fields, List<Where> wheres, List<Order> orders, UserAccount account) {
this.start = start;
this.end = end;
this.fields = fields;
this.wheres = wheres;
this.orders = orders;
this.account = account;
}
@Override
public List<AwbInfo> call() throws Exception {
List<AwbInfo> list = null;
try {
list = awbInfoDao.getAwbInfosV2(start, end, fields, wheres, orders, account);
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
启动多线程,每个线程执行3000条数据。
用到了callable和future和线程池,最后排序
/**
*
* Created by zhang
* Date:2019/02/26
* 执行线程池里的方法,每个线程的任务先放在一个List<Callable<List<AwbInfo>>>集合中,最后用executorService.invokeAll(tasks)执行全部的任务,最后返回List<Future<List<AwbInfo>>>,遍历这个集合放在一个list中,就获得全部的数据了
*/
@Override
@TargetDataSource(name = "cargo_market_slave")
public List<AwbInfo> findAllV2(int numPerPage, int pageNum, List<String> fields, List<Where> wheres, List<Order> orders, UserAccount account)
throws Exception {
// 数据总数
Integer total = awbInfoDao.getAwbInfosTotal(wheres, orders, account);
// 分页数
Integer num = 3000;
// 结果集合
List<AwbInfo> result = new ArrayList<>();
// 需要查询的次数
int times = total / num;
if (total % num != 0) {
times = times + 1;
}
// Callable用于产生结果
List<Callable<List<AwbInfo>>> tasks = new ArrayList<>();
Integer start = 0;
Integer end = total < num ? total : num;
for (int i = 0; i < times; i++) {
Callable<List<AwbInfo>> task = new Task(start, end, fields, wheres, orders, account);
tasks.add(task);
start = num * (i + 1);
end = num;
}
// 定义固定长度的线程池 防止线程过多
ExecutorService executorService = Executors.newFixedThreadPool(15);
// Future用于获取结果
List<Future<List<AwbInfo>>> futures = executorService.invokeAll(tasks);
// 处理线程返回结果
if (futures != null && futures.size() > 0) {
for (Future<List<AwbInfo>> future : futures) {
result.addAll(future.get());
}
}
executorService.shutdown();// 关闭线程池
Collections.sort(result, new Comparator<AwbInfo>() {
@Override
public int compare(AwbInfo o1, AwbInfo o2) {
return o1.getRowNumber().compareTo(o2.getRowNumber());
}
});
return result;
}
最后封装到poi中就可以了
参考资料:https://blog.csdn.net/qq_24075991/article/details/102600727
数据库 数据量大的时候也可以使用批处理查询出来
18 public class JDBCDEMO1 {
19 public static final String DBDRIVER = "com.mysql.jdbc.Driver";
20 public static final String DBURL = "jdbc:mysql://localhost:3306/test";
21 public static final String DBUSER = "root";
22 public static final String DBPASS = "123123";
23
24 public static void main(String[] args) throws Exception {
25 Connection conn=null;
26 PreparedStatement pstmt=null;
27 String sql="INSERT INTO user(name,age)"+"VALUES(?,?)";
28 Class.forName(DBDRIVER);
29 conn=DriverManager.getConnection(DBURL, DBUSER, DBPASS);
30 pstmt=conn.prepareStatement(sql);
31 for(int i=0;i<10;i++){
32 pstmt.setString(1, "赵小蒙 - "+i);
33 pstmt.setInt(2, 20+i);
34 pstmt.addBatch();
35 }
36 int trmp[]=pstmt.executeBatch();
37 System.out.println("更新了"+trmp.length+"条数据。。");
38 pstmt.close();
39 conn.close();
40 }
41 }