CompletableFuture&多线程异步for循环再汇总

博客内容介绍了如何使用Java的CompletableFuture和线程池实现多线程并行处理大量数据,以及如何在处理完成后进行结果的汇总。示例代码展示了如何通过异步执行任务,避免阻塞主线程,并通过CountDownLatch进行同步控制,确保所有任务执行完毕。此外,还提到了线程池的配置和使用,以优化并发性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

无参

  List<HealthGroupDataDTO> groupDataDTOS = new ArrayList<>();
 List<List<Long>> schoolSplitIds = DataUtil.splitData(schoolIds, 4000);
 List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (List<Long> schoolSplitId : schoolSplitIds) {
            futures.add(CompletableFuture.runAsync(() -> {
                try {
                    groupDataDTOS.addAll(healthStatisMapper.selectSchoolTemperList(schoolSplitId, queryTime));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }));
        }
        //等待全部完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

有参

ExecutorService executor = new ThreadPoolExecutor(
            8, 100, 5,
            TimeUnit.MINUTES,
            new ArrayBlockingQueue<>(10000)
    );
List<HealthGroupDataDTO> groupDataDTOS = new ArrayList<>();

    List<CompletableFuture<HealthGroupDataDTO>> fList = new ArrayList<>();
    groupDataDTOS.forEach(groupData->{
        CompletableFuture<HealthGroupDataDTO> f = CompletableFuture.supplyAsync(
                //执行耗时较长的业务代码,这里模拟一下
                ()->{
                    groupData.setTime("");
                    return groupData;
                },
                executor
        );
        fList.add(f);
    });
    // 阻塞,等待所有任务执行完成
    CompletableFuture<Void> all= CompletableFuture.allOf(fList.toArray(new CompletableFuture[0]));
    //因为allOf没有返回值,所以需要通过thenApply回调函数获取结果
    CompletableFuture<List<HealthGroupDataDTO>> allUser=all.thenApply(v-> fList.stream().map(a-> {
        try {
            return a.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return null;
    }).collect(Collectors.toList()));
    groupDataDTOS=allUser.get();

多线程-使用线程池

异步执行汇总

//先定义一个线程池

private final ThreadPoolExecutor poolExecutor= ExecutorBuilder.create().setCorePoolSize(10).setMaxPoolSize(100).build();

 public void importExcel() throws Exception {
        //这个是需要去遍历处理的数据
        List<OWazyLocationVO> excelDataList = .........;
		//这个是最终汇总的 集合数据
        List<WayzLocationResult> dataList = new ArrayList<>();
        
        //Hutool线程工具,异步执行结束后汇总需要用到,若不需要汇总,仅多线程执行,这个countDownLatch 相关可以直接删掉
        CountDownLatch countDownLatch = ThreadUtil.newCountDownLatch(excelDataList.size());
        this.poolExecutor.execute(() -> {
        	 for (OWazyLocationVO pos : excelDataList ) {
        	 	//调用其他服务或查询返回的结果,汇总到dataList 中
				WayzLocationResult wayzLocationResult = forestWayzLocationService.trackPoint(pos);
	 			dataList.add(wayzLocationResult );
				countDownLatch.countDown();
			}
		});
		//汇总,等待多线程结束
        countDownLatch.await();
		log.info("dataList查询多线程处理结束:" + dataList.size());
}
### 设置 `CompletableFuture.supplyAsync` 多个异步任务的超时 当执行多个异步任务并希望设置全局或单个任务的超时时,可以利用 `CompletableFuture` 提供的方法来实现这一目标。对于多个异步任务而言,通常有两种方式处理这些任务:一种是等待所有任务完成;另一种是在任意一个任务完成后立即返回结果。 #### 使用 `orTimeout` Java 的 `CompletableFuture` 类提供了 `orTimeout(long timeout, TimeUnit unit)` 方法用于指定最大等待时间。如果在这个时间内未能得到计算的结果,则会抛出 `CompletionException` 异常[^1]。 ```java Executor executor = Executors.newFixedThreadPool(10); // 创建两个带有不同延迟的任务 CompletableFuture&lt;String> task1 = CompletableFuture.supplyAsync(() -> { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { throw new IllegalStateException(e); } return "Task 1 completed"; }, executor).orTimeout(3, TimeUnit.SECONDS); CompletableFuture&lt;String> task2 = CompletableFuture.supplyAsync(() -> { try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { throw new IllegalStateException(e); } return "Task 2 completed"; }, executor).orTimeout(3, TimeUnit.SECONDS); try { System.out.println(task1.get()); // 这个应该成功打印 System.out.println(task2.get()); // 超过设定的时间将会抛出异常 } catch (Exception e) { System.err.println("One or more tasks failed with exception: " + e.getMessage()); } ``` #### 组合多个任务与超时控制 为了组合多个任务并在它们之间应用统一的逻辑,比如全部失败则触发特定行为,或者只要有一个成功就不再关心其他未完成的任务,可以考虑使用 `allOf` 或者 `anyOf` 配合 `orTimeout` 来达到目的: - **All Of**: 只有所有的未来都完成了才会继续。 - **Any Of**: 只要任何一个未来完成了就会继续。 下面是一个简单的例子展示如何结合这两种方法以及超时机制: ```java import java.util.concurrent.*; import java.util.Arrays; import java.util.List; public class AsyncTasksWithTimeout { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newFixedThreadPool(5); List<CompletableFuture&lt;Void>> futures = Arrays.asList( supplyAsyncWithTimeout(executor, () -> doWork("task1", 2), 3), supplyAsyncWithTimeout(executor, () -> doWork("task2", 4), 3) ); // 尝试获取所有任务的结果,在任何一项超过给定时间后终止整个过程 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) .orTimeout(3, TimeUnit.SECONDS) .whenComplete((v, t) -> { if (t != null) { System.out.println("At least one task timed out."); } else { System.out.println("All tasks finished within time limit."); } }); Thread.sleep(5000); // 确保主线程不会提前结束 executor.shutdown(); } private static <T> CompletableFuture&lt;T> supplyAsyncWithTimeout(Executor executor, Supplier<T> supplier, long timeoutSeconds) { return CompletableFuture.supplyAsync(supplier, executor) .orTimeout(timeoutSeconds, TimeUnit.SECONDS); } private static String doWork(String name, int sleepTimeInSeconds) { try { TimeUnit.SECONDS.sleep(sleepTimeInSeconds); } catch (InterruptedException e) { throw new RuntimeException(e); } return name + ": Done!"; } } ``` 这段代码展示了如何通过 `supplyAsyncWithTimeout` 函数封装带有时限的任务提交,并且可以通过调整参数轻松改变每个任务的最大允许运行时间和线程池大小。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值