使用ThreadPoolExecutor与Callable Future实现多线程时效率无提升如何解决
问题根因
你的代码没有体现多线程效果的核心问题出在循环内调用result.get()的逻辑:
Future.get()是阻塞方法,你每提交一个任务就立刻调用该方法等待任务返回,导致循环必须等上一个任务完全执行完成,才会提交下一个任务,所有任务实际是串行执行的,所以无论线程池大小设置为多少,总耗时都和单线程完全一致。
此外还有两处隐藏的线程安全问题需要修复:
- 若
csvWriter没有做线程安全处理,多线程同时写入会出现CSV内容错乱、数据丢失甚至文件损坏的问题 - 代码中的
response如果是类成员变量,多线程运行时会出现变量覆盖的异常
修复方案
步骤1:调整任务提交与等待逻辑
先将所有任务批量提交到线程池,再统一等待所有任务执行完成,避免提交阶段阻塞。
步骤2:保证CSV写入的线程安全
可以给writeCsv方法加锁,或者让每个线程先生成结果缓存最后汇总写入,避免多线程同时写文件的冲突。
修复后代码示例
private void executeTest(List<String[]> inputArray) throws ExecutionException, InterruptedException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(nThreads);//2, 5, 7 long start = System.currentTimeMillis(); // 存储所有任务的Future对象,暂不阻塞等待结果 List<Future<ApiResponse>> futureList = new ArrayList<>(); for (String[] listOfArray : inputArray) { Callable<ApiResponse> c2 = new Callable<ApiResponse>() { public ApiResponse call() { // 将response改为局部变量,避免线程间变量覆盖 ApiResponse response = runTestCase(listOfArray); try { // 写入CSV时加锁保证线程安全 synchronized (csvWriter) { csvWriter.writeCsv(listOfArray[0], response); } } catch (IOException e) { e.printStackTrace(); } return response; } }; futureList.add(executor.submit(c2)); } System.out.println("nThread :"+nThreads); // 所有任务提交完成后,统一等待执行结束 for (Future<ApiResponse> result : futureList) { result.get(); } // 用完线程池记得关闭 executor.shutdown(); long stop = System.currentTimeMillis(); long timeTaken = stop - start; System.out.println("Total time taken :"+timeTaken+" No of Theads :"+nThreads); }
内容的提问来源于stack exchange,提问作者Dead pool
相关产品推荐
相关产品推荐

