前言
这个异步编排的业务场景简单形容一下,线程A、线程B、线程C,这里存在三个线程任务,A线程又返回值,并且线程C的执行需要线程A执行完后的返回值做条件,线程B不需要返回值,那么这里有些需要返回,有些不需要返回,有些需要等待某些线程的结果只能执行,这样的异步任务需要使用CompletableFutrue来进行异步编排操作!
CompletableFutrue介绍
//Completablefuture提供了四个静态方法来创建一个异步操作。
//static CompletableFutrue<Void > runAsync(Runnable runnable).//以异步的方式运行线程,Runnable无需返回值,默认的异步任务是在默认的线程池中执行的
//public static CompletableFuture<Void> runAsync (Runnable runnable, Executor executor);//以异步的方式运行线程,Runnable无需返回值,可以传入自定义的线程池Executor对象
//public static <U > Completablefuturec > supplyAsync(Supplier < U > supplier);//这个是有返回值的,在默认线程中执行
//public static <U > CompletableFutrue > supplyasync(Supplier U > supplier, Executon executor);//又返回值的,在指定线程中执行
代码编写
/**
* @author TAO
* @description: CompletableFutrue-异步编排
* @date 2020/7/23 20:45
*/
public class NewTestthread {
//创建线程池
public static ExecutorService executorService= Executors.newFixedThreadPool(18);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("主线程开始运行");
//CompletableFuture.runAsync(()->{
// System.out.println("线程开始运行");
// int i=111;
//},executorService);
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);//测试当前线程是否同步
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程开始运行");
int i = 111;
return i;
}, executorService);
System.out.println(future.get());
System.out.println("主线程结束");
}
}
线程逻辑处理完成后回调方法
//public CompletableFuture<T> whencomplete (Biconsumer < ? super T,?super Throwable > action)
//public CompletablefuturecT>whencompleteAsync(Biconsumer < ? super T, ? super Throwable action);
//public CompletableFuturecT>whenCompleteAsync(BiConsumer < ? super T, ? super Throwable action, Executor executor);
//public CompletableFuturecT>exceptionally(Function < Throwable, ? extends Ts fn);
//whenComplete可以处理正常和异常的计算结果, exceptionally处理异常情况。
//whenComplete和whenCompleteAsync的区别:
//whenComplete:是执行当前任务的线程执行继续执行whenComplete的任务。
//eeywhenCompleteAsync:是执行把whenCompleteAsync这个任务继续提交给线程池来进行执行。
//方法不以Async结尾, 意味着Action使用相同的线程执行, 而Async可能会使用其他线程执行(如果是使用相同的线程池, 也可能会被同一个线程选中执行)
代码编写
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author TAO
* @description: CompletableFutrue-异步编排
* @date 2020/7/23 20:45
*/
public class NewTestthread {
//创建线程池
public static ExecutorService executorService = Executors.newFixedThreadPool(18);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("主线程开始运行");
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程ID-->"+Thread.currentThread().getId());
System.out.println("线程开始运行");
int i = 111;
return i;
}, executorService).whenComplete((res,excption)->{
System.out.println("异步线程任务完成了,开始执行回调的任务!!!");
System.out.println("结果-->"+res+"异常是:-->"+excption);
});
System.out.println(future.get());
System.out.println("主线程结束");
}
}
捕获线程异常,并返回值
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程ID-->"+Thread.currentThread().getId());
System.out.println("线程开始运行");
int i = 10/0;
return i;
}, executorService).whenComplete((res,excption)->{
//这里虽然能感知到异常但是无法修改饭后值
System.out.println("异步线程任务完成了,开始执行回调的任务!!!");
System.out.println("结果-->"+res+"异常是:-->"+excption);
}).exceptionally(throwable->{
System.out.println("捕获到异常,可以修改返回值,并返回指定值");
return 10;
});
补充Handle方法
上面演示了whenComplete方法,这个只能感知到线程逻辑执行完成,但是无法修改返回值,就算exceptionally这里捕获到异常能修改,那么也无法满足感知线程逻辑执行完成,并且没有异常,且能修改返回值!那么这里就补充一个Handle方法来满足业务需求!
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程ID-->"+Thread.currentThread().getId());
System.out.println("线程开始运行");
int i = 10/0;
return i;
}, executorService).handle((res,excption)->{
//这里虽然能感知到异常但是无法修改饭后值
System.out.println("异步线程任务完成了,开始执行回调的任务!!!");
System.out.println("结果-->"+res+"异常是:-->"+excption);
if (res!=null){
return 111;
}
if (excption!=null){
return 222;
}
return 0;
});
System.out.println(future.get());
System.out.println("主线程结束");