项目场景:
大数据量的List集合,需要把List集合中的数据批量插入数据库中。
解决方案:
拆分list集合后,然后使用多线程实现
public static void main(String[] args) throws Exception {
// 开始时间
long start = System.currentTimeMillis();
List<String> list = new ArrayList<String>();
for (int i = 1; i <= 3000; i++) {
list.add(i + "");
}
/*动态线程数方式*/
// 每500条数据开启一条线程
int threadSize = 500;
// 总数据条数
int dataSize = list.size();
// 线程数,动态生成
int threadNum = dataSize / threadSize + 1;
/*固定线程数方式
// 线程数
int threadNum = 6;
// 总数据条数
int dataSize = list.size();
// 每一条线程处理多少条数据
int threadSize = dataSize / (threadNum - 1);
*/
// 定义标记,过滤threadNum为整数
boolean special = dataSize % threadSize == 0;
// 创建一个线程池
ExecutorService exec = Executors.newFixedThreadPool(threadNum);
// 定义一个任务集合
List<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>();
Callable<Integer> task = null;
List<String> cutList = null;
// 确定每条线程的数据
for (int i = 0; i < threadNum; i++) {
if (i == threadNum - 1) {
if (special) {
break;
}
cutList = list.subList(threadSize * i, dataSize);
} else {
cutList = list.subList(threadSize * i, threadSize * (i + 1));
}
final List<String> listStr = cutList;
task = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
//业务逻辑,循环处理分段后的list
System.out.println(Thread.currentThread().getName() + "线程:" + listStr);
//......
int logCount = 0; //记录下数量
for (int j = 0; j < listStr.size(); j++) {
logCount++;
}
return logCount;
}
};
// 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
tasks.add(task);
}
exec.invokeAll(tasks);
//总数
int total = 0;
try {
List<Future<Integer>> results = exec.invokeAll(tasks);
for (Future<Integer> future : results) {
//累计线程处理的总记录数
total+=future.get();
}
// 关闭线程池
exec.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("线程任务执行结束");
System.out.println("总共处理了"+total+"条数据,消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
}