Java多线程中Callable任务未完成即执行createCSV的解决方法
问题根源
你的代码里最核心的问题是任务列表tasks没有在每个a和b的循环组合前重新初始化,导致每次迭代都会累积之前的任务。这会让invokeAll处理混合的任务集合,同时createCSV会处理所有历史任务的结果,造成“任务没完成就执行createCSV”的错觉——实际上要么是旧任务的进度干扰了判断,要么是重复处理导致逻辑混乱。
另外要明确:executor.invokeAll(tasks)本身会等待所有提交的任务完成后才返回,只要任务列表是当前批次的,createCSV肯定是在所有calculateRows跑完之后才执行的。
修复步骤
每个
a/b循环内单独初始化任务列表
把tasks的定义放到for (double b : listB)循环内部,确保每个a和b的组合对应独立的任务集合,不会和之前的任务混在一起。替换无效的空等待循环
原代码里while (!executor.isTerminated()) {}是纯空循环,会浪费CPU资源,换成带超时的等待方法更合理。
修复后的核心代码
public static void main(String[] args) { final int MAX_THREADS = 2; ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS); for (int a : listA) { for (double b : listB) { // 每次a/b组合都新建任务列表,避免累积旧任务 List<Callable<RowEarnings>> tasks = new ArrayList<>(); for (int c : listC) { for (int d : listD) { for (int e : listE) { for (int f : listF) { for (double g : listG) { for (double h : listH) { for (double i : listI) { if (i < h) { try { Callable<RowEarnings> task = () -> calculateRows("C://CSV", a, b, c, d, e, f, g, h, i); tasks.add(task); } catch (Exception e) { System.out.println("Error Message"); e.printStackTrace(); } } } } } } } } } try { // invokeAll会等当前tasks里所有任务全跑完才返回结果列表 List<Future<RowEarnings>> results = executor.invokeAll(tasks); // 到这一步所有calculateRows都已完成,放心执行createCSV createCSV(directory, results, a, b); } catch (InterruptedException e) { System.out.println("Error while invoking tasks."); e.printStackTrace(); } } } executor.shutdown(); try { // 替换空循环为带超时的等待,超时后强制关闭线程池 if (!executor.awaitTermination(1, TimeUnit.HOURS)) { executor.shutdownNow(); } System.out.println("TEST COMPLETE"); } catch (InterruptedException e) { System.out.println("Thread execution interrupted."); executor.shutdownNow(); Thread.currentThread().interrupt(); } }
额外优化建议
- 任务分批处理:如果任务量达到百万级,一次性提交所有任务可能占满内存,可以把任务拆成多批,每批执行完就写入部分数据(不过你的逻辑是按a/b生成单独CSV,可根据实际情况调整)。
- 调整线程池大小:别硬写死2个线程,用
Runtime.getRuntime().availableProcessors()获取CPU核心数来设置,避免线程过多导致上下文切换浪费资源。 - 加进度日志:在
calculateRows里加个计数,或者提交任务后打印当前批次的任务总数,方便你跟踪真实进度,不会再误判任务完成情况。
内容的提问来源于stack exchange,提问作者PondleDondle
相关产品推荐
相关产品推荐

