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

CompletionService和CompletableFuture

时间:2023-04-01 17:57:03 Java

在jdk1.8之前,我们使用FutureTask的get方法获取异步执行的结果。在演示之前,粘贴共享代码。ConcurrentSupport:publicclassConcurrentSupport{publicstaticStringprocessOne(){try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}返回getNow()+"#one";}publicstaticStringprocessTwo(){尝试{TimeUnit.SECONDS.sleep(2);}catch(InterruptedExceptione){e.printStackTrace();}返回getNow()+"#two";}publicstaticStringprocessThree(){尝试{TimeUnit.SECONDS.sleep(3);}catch(InterruptedExceptione){e.printStackTrace();}返回getNow()+"#three";}publicstaticStringgetNow(){returnLocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));}}TaskA:classTaskAimplementsCallable{@OverridepublicObjectcall()throwsException{returnConcurrentSupport.processOne();}}TaskB:类TaskB实现Callable{@OverridepublicObjectcall()throwsException{returnConcurrentSupport.processTwo();}}TaskC:类TaskC实现Callable{@OverridepublicObjectcall()throwsException{returnConcurrentSupport.processThree();}}通常情况下,比如有3个任务,分别耗时1s、2s、3s。同步执行时,整个耗时6sSystem.out.println(ConcurrentSupport.processOne());System.out.println(ConcurrentSupport.processTwo());System.out.println(ConcurrentSupport.processThree());System.out.println("耗时:"+(System.currentTimeMillis()-start));}}FutureTask在使用FutureTask的情况下,是耗时最长的一个,所以最后的时间是3s。publicclassFutureTaskDemo{publicstaticvoidmain(String[]args)throwsExecutionException,InterruptedException{//创建线程池ExecutorServiceexecutor=Executors.newFixedThreadPool(3);长启动=System.currentTimeMillis();//创建FutureTaskFutureTasktaskA=newFutureTask(newTaskA());FutureTasktaskB=newFutureTask(newTaskB());FutureTasktaskC=newFutureTask(newTaskC());执行器.提交(任务A);执行器.提交(任务B);执行器.提交(任务C);System.out.println(taskC.get());System.out.println(taskA.get());System.out.println(taskB.get());System.out.println("耗时:"+(System.currentTimeMillis()-start));}}CompletionService但FutureTask也有一个小缺陷。比如上面的TaskC执行时间最长,直接阻塞了TaskA和TaskB的打印任务。结果是三,一,二。有什么方法可以打印(或以其他方式处理结果)结果,无论哪个任务首先成功执行?这就是CompletionService所做的。从结果可以看出,打印了一、二、三。publicclassCompletionServiceDemo{publicstaticvoidmain(String[]args)throwsInterruptedException,ExecutionException{//创建线程池ExecutorServiceexecutor=Executors.newFixedThreadPool(3);长启动=System.currentTimeMillis();//创建CompletionServiceCompletionServicecs=newExecutorCompletionService<>(executor);//用于保存Future对象List>futures=newArrayList<>(3);//提交FutureTaskfutures.add(cs.submit(newTaskC()));futures.add(cs.submit(newTaskA()));futures.add(cs.submit(newTaskB()));for(inti=0;i<3;i++){字符串结果=cs.take().get();System.out.println(结果);}System.out.println("耗时:"+(System.currentTimeMillis()-start));}}CompletableFuture如果有一个任务是这样的,A1执行完之后,A2执行,B1执行,B2执行,A2和B2都执行,然后C执行。JDK1.8提供了CompletableFuture这个优雅的解决方案。例如,在下面的示例中,f3在执行完f1和f2之后执行。CompletableFuture方法中,runAsync没有返回值,supplyAsync有返回值。公共类CompletableFutureDemo{publicstaticvoidmain(String[]args){CompletableFuturef1=CompletableFuture.runAsync(()->{Stringone=ConcurrentSupport.processOne();System.out.println(one);});CompletableFuturef2=CompletableFuture.supplyAsync(()->{Stringtwo=ConcurrentSupport.processTwo();System.out.println(two);返回二;});CompletableFuturef3=f1.thenCombine(f2,(__,tf)->{System.out.println("f3#"+tf);返回"f3";});f3.join();}}