【视频笔记】CompletableFuture功能究竟有多强?Spring底层全在用它?CompletableFuture才是并发编程的正确打开方式!
Future的get方法会阻塞
CompletableFuture,可以组合多个异步任务
如可以拿到异步任务中最快的一个,传统异步编程是很麻烦的
如可以在一个任务执行完以后,去执行另一个任务,传统方式是join或嵌套任务(可能回调地狱)
CompletableFuture提供了异步回调来处理
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CompletableFutureTest { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000L); return "future task finished"; } }); new Thread(futureTask).start(); // 阻塞执行 System.out.println(futureTask.get()); System.out.println("main execute finished"); } } ----- future task finished main execute finished
CompletableFuture 异步执行:
runAsync()方法执行任务是没有返回值的
supplyAsync()方法执行任务则支持返回值
public static void completableFutureTask() { CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> { System.out.println("runAsync finished, no response data"); }); CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync finished, response hahaha "); return "hahaha"; }); System.out.println(supplyAsync.join()); }
组合处理
anyOf 返回跑的最快的那个future。最快的如果异常都玩完
allOf 全部并行执行,如果需要获得返回值,需要配合thenApply, 异常会抛出,不影响其他任务
CompletableFuture<Object> futureA = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000L); System.out.println("A has finished"); return "A has finished"; } catch (InterruptedException e) { throw new RuntimeException(e); } }); CompletableFuture<Object> futureB = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(500L); System.out.println("B has finished"); return "B has finished"; } catch (InterruptedException e) { throw new RuntimeException(e); } }); CompletableFuture<Object> anyFutures = CompletableFuture.anyOf(futureA, futureB); System.out.println(anyFutures.join()); }
上面任务B较快执行完,如果B异常,则整体结果异常
CompletableFuture<Object> futureB = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500L);
throw new RuntimeException("B error");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
Exception in thread "main" java.util.concurrent.CompletionException: java.lang.RuntimeException: B error at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1770) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: java.lang.RuntimeException: B error at com.rocky.CompletableFutureTest.lambda$completableFutureAnyOf$3(CompletableFutureTest.java:54) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ... 6 more
allOf
public static void completableFutureAllOf() throws ExecutionException, InterruptedException { CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000L); return "A has finished"; } catch (InterruptedException e) { throw new RuntimeException(e); } }); CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000L); return "B has finished"; } catch (InterruptedException e) { throw new RuntimeException(e); } }); CompletableFuture<String> future = CompletableFuture.allOf(futureA, futureB).thenApply(res -> { return futureA.join() + " " + futureB.join(); }); System.out.println(future.get()); }
CompletableFuture的thenCompose和thenApply有什么区别?
参考:CompletableFuture的thenCompose和thenApply有什么区别?CompletableFutu - 掘金
异步回调
whenComplete() 没有返回值,且返回的CompletableFuture为任务结果,而非回调结果
handle() 有返回值,且返回的CompletableFuture为回调结果
链式处理
thenRun(Runnable runnable)对异步任务的结果进行操作,不能传入参,也没有返回值。不会阻塞主线程
thenAccept(Consumer consumer) 可传入参数
thenApply(Function function) 可传入参数,并返回结果
thenRun
public static void completableFutureThenRun(){ CompletableFuture<Void> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync finished");// 这里是异步执行,主线程之外 return "supplyAsync result"; }).thenRun(() -> { System.out.println("cannot get supplyAsync result, thenRun finished"); }).thenRun(() -> { System.out.println("cannot get supplyAsync result, thenRun2 finished"); }); System.out.println("主线程"); supplyAsyncFinished.join(); }
thenAccept
public static void completableFutureThenAccept(){ CompletableFuture<Void> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync finished"); return 5; }).thenAccept(num -> { System.out.println("can get supplyAsync result" +num * 4); }); System.out.println("主线程"); supplyAsyncFinished.join(); }
thenApply
public static void completableFutureThenApply() { CompletableFuture<Integer> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync finished"); return 5; }).thenApply(res -> res * 5) //用到上一步的结果 .thenApply(res -> res + 3); System.out.println("主线程"); System.out.println(supplyAsyncFinished.join()); }
上面链式方法,出现异常,后面的任务会中断
处理任务重感知不到异常
异常会通过get抛出到主线程
whenComplete
public static void completableFutureWhenComplete() { CompletableFuture<Integer> supplyAsyncFinished = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync finished"); return 5 / 0; }).whenComplete((res, throwable) -> { System.out.println("exec whenComplete method, and print execption msg:"+throwable.getMessage()); }); System.out.println("主线程"); System.out.println(supplyAsyncFinished.join()); }
参考:CompletableFuture功能究竟有多强?Spring底层全在用它?CompletableFuture才是并发编程的正确打开方式!_哔哩哔哩_bilibili
浙公网安备 33010602011771号