当前位置: 首页 > 后端技术 > Java

Java实现等待多个子任务完成后再继续执行主流程

时间:2023-04-01 23:34:57 Java

在Java中可以使用CountDownLatch或CompletableFuture等待多个子任务完成再继续执行主流程。一、基本实现1、使用CountDownLatch实现importjava.util.concurrent.CountDownLatch;publicclassMain{publicstaticvoidmain(String[]args)throwsInterruptedException{inttaskNum=5;CountDownLatchcountDownLatch=newCountDownLatch(taskNum);for(inti=0;i{try{//子任务执行代码//...}catch(Exceptione){e.printStackTrace();}finally{//完成一个子任务,将计数器减1countDownLatch.countDown();}}).start();}//等待所有子任务完成countDownLatch.await();//所有子任务完成后继续执行主进程//...}}上面CountDownLatch的示例代码中,如果在子任务执行过程中抛出异常,主线程无法立即感知到,所以异常处理需要在子任务中执行,否则主线程可能会一直等待失败。2、使用CompletableFuture实现1)withreturnvalueimportjava.util.List;importjava.util.concurrent.CompletableFuture;importjava.util.stream.Collectors;importjava.util.stream.Stream;publicclassMain{publicstaticvoidmain(String[]args){List>futures=Stream.of(1,2,3,4,5).map(i->CompletableFuture.supplyAsync(()->{try{//子任务的执行代码,返回一个字符串结果//...}catch(Exceptione){//处理子任务执行过程中的异常e.printStackTrace();returnnull;//返回null给表示子任务执行失败}return"Result"+i;})).collect(Collectors.toList());//等待所有子任务完成并得到结果Listresults=futures.stream().map(CompletableFuture::join).filter(result->结果!=null).collect(Collectors.toList());//所有子任务完成后,继续执行主流程//...}}2)无返回值importjava.util.List;importjava.util.concurrent.CompletableFuture;导入java.util.stream.Collectors;导入java.util.stream.Stream;公共类Main{publicstaticvoidmain(String[]args){List>futures=Stream。of(1,2,3,4,5).map(i->CompletableFuture.runAsync(()->{try{//子任务执行代码,返回字符串结果//...}catch(Exceptione){//在子任务执行期间处理异常e.printStackTrace();//...}})).collect(Collectors.toList());//等待所有子任务完成CompletableFuture.allOf(futures.toArray(newCompletableFuture[0])).join();//所有子任务完成后,继续执行上面Co中的主流程//...}}在mpletableFuture的示例代码中,如果子任务执行过程中抛出异常,主线程无法立即感知到,所以需要在子任务中进行异常处理,否则主线程可能会一直等待下去。2、CompletableFuture超时处理CompletableFuture是基于Future和CompletionStage的异步编程框架,允许开发者通过简单的API组合多个异步任务,实现更灵活高效的异步编程方式。CompletableFuture还支持异常处理、超时等特性,可以帮助开发者更好的处理复杂的异步场景。1、代码实现stream.Collectors;importjava.util.stream.Stream;publicclassMain{publicstaticvoidmain(String[]args){Durationtimeout=Duration.ofSeconds(5);List>futures=Stream.of(1,2,3,4,5).map(i->CompletableFuture.supplyAsync(()->{try{//子任务执行代码,返回字符串结果//...}catch(Exceptione){//处理子任务执行过程中的异常e.printStackTrace();returnnull;//返回null表示子任务执行失败}return"Result"+i;})).collect(收集器.toList());//等待所有孩子任务完成并得到结果Listresults=futures.stream().map(future->{try{returnfuture.get(timeout.toMillis(),java.util.concurrent.TimeUnit.MILLISECONDS);}catch(InterruptedException|ExecutionException|TimeoutExceptione){//处理子任务执行过程中的异常或超时e.printStackTrace();future.cancel(true);//取消未完成的子任务returnnull;//返回null表示子任务任务执行失败}}).filter(结果->结果!=null).collect(Collectors.toList());//所有子任务完成后,继续执行主流程//...}}2、Stream.of(1,2,3,4,5)是必要的吗?可以更换吗?上面的示例代码中,Stream.of(1,2,3,4,5)这行代码不是必须的,只是为了演示一种使用StreamAPI创建CompletableFuture对象的方法,在实际开发中,可能有创建CompletableFuture对象的不同方式,例如通过调用其他方法、读取文件、调用远程接口等。Stream.of()方法用于创建由指定元素组成的顺序流。在这里,我们使用Stream.of(1,2,3,4,5)创建一个包含整数1到5的顺序流,然后在这个流上使用map()方法将每个整数转换为CompletableFuture对象,最后通过collect()方法将所有CompletableFuture对象收集到一个列表中。如果有其他方法创建CompletableFuture对象,可以根据实际情况使用不同的方法创建,而不是使用Stream.of()方法。CompletableFuture对象可以通过多种方式创建,例如使用CompletableFuture.supplyAsync()方法、使用CompletableFuture.runAsync()方法、使用CompletableFuture.completedFuture()方法等,具体取决于您的业务需求。