线程池流程:
核心线程--》阻塞队列--》最大线程数--》拒绝策略(默认的是把任务丢掉,并且抛出异常)
一个线程池核心是7,最大是20,队列是50,100并发进来怎么执行?
首先是7个并发占用核心线程池立即执行,50个进入队列,再开13个线程开始执行,剩下的30个会使用拒绝策略,如果不想抛弃可以使用CallerRunsPolicy策略异步执行
常用的几个线程池:
Executors.newCachedThreadPool(); core的大小是0,所有都可以回收
Executors.newFixedThreadPool(); core的大小是max的大小,所有都不可以回收
Executors.newScheduledThreadPool(); 定时任务的线程池
Executors.newSingleThreadExecutor(); 单线程的线程池(在分布式情况下,保证双写一致,需要将相同的业务留给同一台服务器或者线程来处理)
CompletableFuture异步编排
Future接口的最大特点就是能获取到异步任务结果
业务场景:一个页面展示需要好几个远程调用才能完成,而且这些远程调用存在逻辑关系
有四个静态方法来创建一个异步操作
static CompletableFuture<Void> runAsync(Runnable runnable) public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。
- runAsync方法不支持返回值。
- supplyAsync可以支持返回值。
计算完成时回调:
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action); public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action); public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor); public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn);
whenComplete可以处理正常和异常的计算结果,exceptionally处理异常情况。BiConsumer<? super T,? super Throwable>可以定义处理业务
whenComplete 和 whenCompleteAsync 的区别:
- whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
- whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。
方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
方法完成后可以调用handle方法来对结果进行处理:
public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn); public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn); public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);
handle 是执行任务完成时对结果的处理。
handle 是在任务完成后再执行,还可以处理异常的任务。
串行化
- thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值。
- thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
- thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun的后续操作
- 带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn) public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) public CompletionStage<Void> thenAccept(Consumer<? super T> action); public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action); public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor); public CompletionStage<Void> thenRun(Runnable action); public CompletionStage<Void> thenRunAsync(Runnable action); public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
Function<? super T,? extends U>
T:上一个任务返回结果的类型
U:当前任务的返回值类型
任务组合-都要完成
- 两个任务必须都完成,触发该任务。
- thenCombine:组合两个future,获取两个future的返回结果,并返回当前任务的返回值
- thenAcceptBoth:组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值。
- runAfterBoth:组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务。
public <U,V> CompletableFuture<V> thenCombine( CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn); public <U,V> CompletableFuture<V> thenCombineAsync( CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn); public <U,V> CompletableFuture<V> thenCombineAsync( CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor); public <U> CompletableFuture<Void> thenAcceptBoth( CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action); public <U> CompletableFuture<Void> thenAcceptBothAsync( CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action); public <U> CompletableFuture<Void> thenAcceptBothAsync( CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor); public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action); public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action); public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor);
public static void main(String[] args) { CompletableFuture.supplyAsync(() -> { return "hello"; }).thenApplyAsync(t -> { return t + " world!"; }).thenCombineAsync(CompletableFuture.completedFuture(" CompletableFuture"), (t, u) -> { return t + u; }).whenComplete((t, u) -> { System.out.println(t); }); }
两任务组合 - 一个完成
- 当两个任务中,任意一个future任务完成的时候,执行任务。
- applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。
- acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。
- runAfterEither:两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值。
public <U> CompletableFuture<U> applyToEither( CompletionStage<? extends T> other, Function<? super T, U> fn); public <U> CompletableFuture<U> applyToEitherAsync( CompletionStage<? extends T> other, Function<? super T, U> fn); public <U> CompletableFuture<U> applyToEitherAsync( CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor); public CompletableFuture<Void> acceptEither( CompletionStage<? extends T> other, Consumer<? super T> action); public CompletableFuture<Void> acceptEitherAsync( CompletionStage<? extends T> other, Consumer<? super T> action); public CompletableFuture<Void> acceptEitherAsync( CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor); public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action); public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action); public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action, Executor executor);
多任务组合
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs); public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs);
allOf:等待所有任务完成
anyOf:只要有一个任务完成
public static void main(String[] args) { List<CompletableFuture> futures = Arrays.asList(CompletableFuture.completedFuture("hello"), CompletableFuture.completedFuture(" world!"), CompletableFuture.completedFuture(" hello"), CompletableFuture.completedFuture("java!")); final CompletableFuture<Void> allCompleted = CompletableFuture.allOf(futures.toArray(new CompletableFuture[]{})); allCompleted.thenRun(() -> { futures.stream().forEach(future -> { try { System.out.println("get future at:"+System.currentTimeMillis()+", result:"+future.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }); }); }
get future at:1568892339473, result:hello
get future at:1568892339473, result: world!
get future at:1568892339473, result: hello
get future at:1568892339473, result:java!