在 Java 中,ExecutorService 常用于并发处理任务。当数据量很大时,通常会把数据分批(分片)提交给线程池,避免一次创建过多任务或 OOM。下面从思路 → 示例 → 注意事项一步步说明。
public static <T> List<List<T>> split(List<T> list, int batchSize) {
List<List<T>> result = new ArrayList<>();
for (int i = 0; i < list.size(); i += batchSize) {
result.add(list.subList(i, Math.min(list.size(), i + batchSize)));
}
return result;
}
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Integer> data = IntStream.range(0, 1000)
.boxed()
.collect(Collectors.toList());
int batchSize = 100;
List<List<Integer>> batches = split(data, batchSize);
List<Future<?>> futures = new ArrayList<>();
for (List<Integer> batch : batches) {
futures.add(executor.submit(() -> {
// 处理每一批数据
for (Integer item : batch) {
System.out.println(Thread.currentThread().getName() + " : " + item);
}
}));
}
// 等待所有任务完成
for (Future<?> future : futures) {
future.get();
}
executor.shutdown();
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Callable<Void>> tasks = new ArrayList<>();
for (List<Integer> batch : batches) {
tasks.add(() -> {
batch.forEach(System.out::println);
return null;
});
}
executor.invokeAll(tasks);
executor.shutdown();
✅ invokeAll 会阻塞直到所有任务完成
如果数据量极大(如百万级),不建议一次性拆分:
ExecutorService executor = Executors.newFixedThreadPool(4);
BlockingQueue<List<Integer>> queue = new LinkedBlockingQueue<>();
// 生产者
executor.submit(() -> {
for (List<Integer> batch : batches) {
queue.put(batch);
}
});
// 消费者
for (int i = 0; i < 4; i++) {
executor.submit(() -> {
while (true) {
List<Integer> batch = queue.poll(1, TimeUnit.SECONDS);
if (batch == null) break;
batch.forEach(System.out::println);
}
});
}
✅ 线程池大小
CPU + 1✅ 批大小
✅ 异常处理
try {
future.get();
} catch (ExecutionException e) {
e.getCause().printStackTrace();
}
✅ 一定要 shutdown 否则程序不会退出
ExecutorService 分批处理 = 数据切片 + 每批一个任务 + 线程池并发执行
如果你有具体场景(如数据库、文件、Spring、CompletableFuture),我可以给你更贴合的示例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。