Asynchronous Java programming tools CompletableFuture

CompletableFuture Profile

JDK 1.8 provides CompletableFuture to support asynchronous programming, we can use CompletableFuture to achieve very fast asynchronous programming, CompletableFuture provides serial, parallel, brings together three modes available to us to use

Instructions

create

public 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)

We can be created by the above four API CompletableFuture objects, API is divided into two categories, one is no return runAsync value, one is the return value of supplyAsync, each of the following categories partakers into two subcategories, One is to use the default Fork / Join the thread pool, thread pool is to use their own definition of

Serial call

CompletableFuture<U> thenApply(Function<? super T,? extends U> fn);
CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn);
CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

CompletableFuture<Void> thenAccept(Consumer<? super T> action);
CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action);
CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)
                                                
CompletableFuture<Void> thenRun(Runnable action);
CompletableFuture<Void> thenRunAsync(Runnable action);
CompletableFuture<Void> thenRunAsync(Runnable action,Executor executor)

CompletableFuture<R> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
CompletableFuture<R> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn,Executor executor)

Serial call provides the above 8 API, divided into four categories, one by one explain:

  • thenApply you need to pass a series Function <? super T ,? extends U> parameter T represents to the Senate, U on behalf of the Senate, so thenApply series can be passed parameters can also return results

  • thenAccept series will pass a Consumer <? super T>, T is the Senate, so thenAccept parameters can be passed, but will not return results

  • thenRun need to pass a series Runnale, so this series has neither to the Senate would not be effective

  • thenCompose series and series thenApply same results, but the need to open a sub-task to execute, from the incoming parameters can also be seen, accepts a parameter Function of a CompletionStage, CompletionStage CompletableFuture is implemented interface implementation class that is specific to the receiving a CompletableFuture objects

With each category * and * Async two kinds of API, the difference is that the task will be executed with Async threw Fork / Join the thread pool, with no Async to be executed by a thread directly in front of the task, it can even bring Async specify the thread pool

parallel

Parallel is better understood, is to create multiple CompletableFuture, so that the task to be performed in parallel

Aggregation

Aggregation is divided into two, one of the AND convergence, a convergence is OR, AND simply means that the convergence of convergence required tasks are completed only after aggregation method can be performed while the OR convergence as long as you can perform a task is completed down , the convergence API may be executed in parallel CompletableFuture a converging CompletableFuture

AND convergence

CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);
CompletableFuture<V> thenCombineAsync( CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn, Executor executor)

CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action));
CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action);
CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor)      

CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action);
CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor)                                                    

AND convergence API provides three types, and similar serial API API functionality, thenCombine provides the ability to have the parameters and the parameters, thenAcceptBoth only provides the ability of the parameters, no return value, runAfterBoth neither into nor out of the reference ginseng

OR convergence

CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn,Executor executor)

CompletableFuture<Void> acceptEither( CompletionStage<? extends T> other, Consumer<? super T> action)
CompletableFuture<Void> acceptEitherAsync( CompletionStage<? extends T> other, Consumer<? super T> action)
CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor)

CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action)
CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)
CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)                                                       

OR and AND aggregation aggregation also similar, the API provides three types, functions of the method may be performed with reference to a method AND aggregation

Exception Handling

CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);
        
CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action));
CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
CompletableFuture<T> whenCompleteAsync( BiConsumer<? super T, ? super Throwable> action, Executor executor)
        
CompletableFuture<U> handle( BiFunction<? super T, Throwable, ? extends U> fn);
CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)

Providing three types of exception handling API:

  • exceptionally similar to the try-catch, if there is an exception to an exception we can get through to the Senate
  • whenComplete you can get results CompletableFuture and can be abnormal by the second argument (if any), and can also capture this exception in the main thread
  • handle and whenComplete similar, but he can also return a result, and whenComplete difference is that there's an exception can not be captured in the main thread

example

package com.demo;

import java.util.concurrent.CompletableFuture;

public class Test {
    
    public static void main(String[] args){

        CompletableFuture<String> f1 = CompletableFuture.runAsync(()->{
            System.out.println("T1:start");
            sleep(1000);
            System.out.println("T1: doing sth");
            sleep(5000);
        }).thenRunAsync(()-> System.out.println("T1 : next task")).thenApply((__)-> {
            System.out.println("T1 task end");
            return " T1 result";
        });

        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(()->{
            System.out.println("T2: start");
            sleep(1000);
            System.out.println("T2: doing sth");
            sleep(2000);
            return " T2:result";
        }).thenApply(s-> s+ "!!!").thenCompose(s -> CompletableFuture.supplyAsync(s::toUpperCase));

        CompletableFuture<String> f3 = f1.thenCombine(f2,(r1,r2)->{
            System.out.println("T1 result :" + r1);
            System.out.println("T2 result:" + r2);
            return "t1 t2 end";
        });


        System.out.println(f3.join());

        System.out.println("--------------");

        /**
         * exceptionally处理异常情况
         * result:
         * java.lang.ArithmeticException: / by zero
         * 0
         */
        CompletableFuture<Integer> f4 = CompletableFuture.supplyAsync(()->1/0)
                .thenApply(i->i*i)
                .exceptionally((throwable -> {
                    System.out.println(throwable.getMessage());
                    return 0;
                }));
        System.out.println(f4.join());
        System.out.println("--------------");
        /**
         * whenComplete处理异常情况
         * result : null, error : java.lang.ArithmeticException: / by zero
         * enter exception block
         *
         * Process finished with exit code 0
         *
         */
        try {
            CompletableFuture<Integer> f5 = CompletableFuture.supplyAsync(()->1/0)
                    .thenApply(i->i*i)
                    .whenComplete((i,t)-> {
                        System.out.println("result : " +i+ ", error : " + t.getMessage());
                    });

            System.out.println(f5.join());
        }catch (Exception e){
            System.out.println("enter exception block");
        }
        System.out.println("--------------");
        /**
         * handle处理异常情况
         * result : null, error : java.lang.ArithmeticException: / by zero
         * 0
         *
         * Process finished with exit code 0
         *
         */
        try {
            CompletableFuture<Integer> f6 = CompletableFuture.supplyAsync(()->1/0)
                    .thenApply(i->i*i)
                    .handle((i,t)-> {
                        System.out.println("result : " +i+ ", error : " + t.getMessage());
                        return 0;
                    });

            System.out.println(f6.join());
        }catch (Exception e){
            System.out.println("enter exception block");
        }
    }

    private static void sleep(long time){
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

A result

T1:start
T2: start
T1: doing sth
T2: doing sth
T1 : next task
T1 task end
T1 result : T1 result
T2 result: T2:RESULT!!!
t1 t2 end
--------------
java.lang.ArithmeticException: / by zero
0
--------------
result : null, error : java.lang.ArithmeticException: / by zero
enter exception block
--------------
result : null, error : java.lang.ArithmeticException: / by zero
0

Process finished with exit code 0

Guess you like

Origin www.cnblogs.com/mrmoo/p/10993734.html