分享知识 传递快乐
使用多线程的方式批量处理数据操作。示例如下:
示例1:单线程多批次
public static void test(List<String> listData) {
long beginTime = System.currentTimeMillis();
// CPU内核数+1
int threadSize = Runtime.getRuntime().availableProcessors() + 1;
// 数据大小
int dataSize = listData.size();
// 方法一:批次大小(每个线程要处理数据量)
int batchSize = (dataSize - 1) / threadSize + 1;
System.out.println(batchSize);
// 方法二:批次大小(每个线程要处理数据量)
int batchSize2 = dataSize / threadSize + 1;
if (dataSize % threadSize == 0) {
batchSize2 = batchSize2 - 1;
}
System.out.println(batchSize2);
// 批次处理数
int batchCount = (int) Math.ceil(1.0 * dataSize / batchSize);
System.out.println(batchCount);
// 根据批次数遍历数据
for (int i = 0; i < batchCount; i++) {
int start = i * batchSize;
int end = Math.min(start + batchSize, dataSize);
// 批次数据
List<String> batchData = listData.subList(start, end);
log.info("第{}批次:start={}, end={}, batchSize={}, batchData={}", i, start, end, batchData.size(), JSONUtil.toJsonStr(batchData));
}
executorService.shutdown();
}
示例2:线程池无返回值
public static void test2(List<String> listData) {
long beginTime = System.currentTimeMillis();
// CPU内核数+1
int threadSize = Runtime.getRuntime().availableProcessors() + 1;
// 数据大小
int dataSize = listData.size();
// 方法一:批次大小(每个线程要处理数据量)
int batchSize = (dataSize - 1) / threadSize + 1;
System.out.println(batchSize);
// 方法二:批次大小(每个线程要处理数据量)
// int batchSize2 = dataSize / threadSize + 1;
// if (dataSize % threadSize == 0) {
// batchSize2 = batchSize2 - 1;
// }
// System.out.println(batchSize2);
// 批次处理数
int batchCount = (int) Math.ceil(1.0 * dataSize / batchSize);
System.out.println(batchCount);
// 初始化线程池
ExecutorService executorService = new ThreadPoolExecutor(batchCount,// 核心线程池大小
100,// 线程池最大容量大小
0L,// 线程池空闲时,线程存活的时间
TimeUnit.MILLISECONDS,// 时间单位
new LinkedBlockingQueue<Runnable>()// 任务队列
);
// 根据批次数遍历数据
for (int i = 0; i < batchCount; i++) {
int start = i * batchSize;
int end = Math.min(start + batchSize, dataSize);
// 批次数据
List<String> batchData = listData.subList(start, end);
log.info("第{}批次:start={}, end={}, batchSize={}", i, start, end, batchData.size());
executorService.submit(() -> {
log.info(JSONUtil.toJsonStr(batchData));
});
}
executorService.shutdown();
}
示例3:线程池有返回值
public static void test3(List<String> listData) throws Exception {
long beginTime = System.currentTimeMillis();
// CPU内核数+1
int threadSize = Runtime.getRuntime().availableProcessors() + 1;
// 数据大小
int dataSize = listData.size();
// 批次大小(每个线程要处理数据量)
int batchSize = (dataSize - 1) / threadSize + 1;
System.out.println(batchSize);
// 批次处理数
int batchCount = (int) Math.ceil(1.0 * dataSize / batchSize);
System.out.println(batchCount);
// 初始化线程池
ExecutorService executorService = new ThreadPoolExecutor(batchCount,// 核心线程池大小
100,// 线程池最大容量大小
0L,// 线程池空闲时,线程存活的时间
TimeUnit.MILLISECONDS,// 时间单位
new LinkedBlockingQueue<Runnable>()// 任务队列
);
// 根据批次数遍历数据
for (int i = 0; i < batchCount; i++) {
int start = i * batchSize;
int end = Math.min(start + batchSize, dataSize);
// 批次数据
List<String> batchData = listData.subList(start, end);
log.info("第{}批次:start={}, end={}, batchSize={}", i, start, end, batchData.size());
Future<Boolean> future = executorService.submit(() -> {
for (String str : batchData) {
log.info(JSONUtil.toJsonStr(batchData));
}
return true;
});
// 返回每个线程处理的结果(顺序)
log.info(future.get() + "");
}
executorService.shutdown();
}
示例4:线程池有返回值
public static void test4(List<String> listData) throws Exception {
long beginTime = System.currentTimeMillis();
// CPU内核数+1
int threadSize = Runtime.getRuntime().availableProcessors() + 1;
// 数据大小
int dataSize = listData.size();
// 批次大小(每个线程要处理数据量)
int batchSize = (dataSize - 1) / threadSize + 1;
System.out.println(batchSize);
// 批次处理数
int batchCount = (int) Math.ceil(1.0 * dataSize / batchSize);
System.out.println(batchCount);
// 初始化线程池
ExecutorService executorService = new ThreadPoolExecutor(batchCount,// 核心线程池大小
100,// 线程池最大容量大小
0L,// 线程池空闲时,线程存活的时间
TimeUnit.MILLISECONDS,// 时间单位
new LinkedBlockingQueue<Runnable>()// 任务队列
);
// 定义一个任务集合
List<Callable<Boolean>> tasks = new ArrayList<>();
// 根据批次数遍历数据
for (int i = 0; i < batchCount; i++) {
int start = i * batchSize;
int end = Math.min(start + batchSize, dataSize);
// 批次数据
List<String> batchData = listData.subList(start, end);
log.info("第{}批次:start={}, end={}, batchSize={}", i, start, end, batchData.size());
Future<Boolean> future = executorService.submit(() -> {
for (String str : batchData) {
log.info(JSONUtil.toJsonStr(batchData));
}
return true;
});
// 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
tasks.add(() -> {
for (String str : batchData) {
log.info(JSONUtil.toJsonStr(batchData));
}
return true;
});
}
List<Future<Boolean>> futures = executorService.invokeAll(tasks);
for (Future<Boolean> future : futures) {
// 返回每个线程处理的结果(顺序)
log.info(future.get() + "");
}
executorService.shutdown();
}
注意:
如果使用多线程最好给每个线程命名,方便查看日志和定位问题。