-
CompletableFuture.supplyAsync
表示创建带返回值的异步任务的,相当于ExecutorService submit(Callable task) 方法
-
CompletableFuture.runAsync
表示创建无返回值的异步任务
-
CompletableFuture.thenApply
和
CompletableFuture.thenApplyAsync
表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中
(
注:job1执行结束后,将job1的方法返回值作为入参传递到job2中并立即执行job2。thenApplyAsync与thenApply的区别在于,前者是将job2提交到线程池中异步执行,实际执行job2的线程可能是另外一个线程,后者是由执行job1的线程立即执行job2,即两个job都是同一个线程执行的)
-
CompletableFuture.thenAccept
thenAccept 同 thenApply 接收上一个任务的返回值作为参数,但是无返回值
-
CompletableFuture.thenRun
thenRun 的方法没有入参,也没有返回值
-
CompletableFuture.exceptionally
exceptionally方法指定某个任务执行异常时执行的回调方法,会将抛出异常作为参数传递到回调方法中。
-
CompletableFuture.whenComplete
是当某个任务执行完成后执行的回调方法,会将执行结果或者执行期间抛出的异常传递给回调方法,如果是正常执行则异常为null,回调方法对应的CompletableFuture的result和该任务一致,如果该任务正常执行,则get方法返回执行结果,如果是执行异常,则get方法抛出异常
@Test
public void test10() throws Exception {
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
if(true){
throw new RuntimeException("test");
}else{
return 1.2;
});
CompletableFuture<Double> cf2=cf.whenComplete((a,b)->{
if(b!=null){
log.error("cf执行异常,异常信息={}",b.getMessage());
}else{
log.info("cf执行正常,没有抛任何异常。且cf执行的结果={}",a);
});
System.out.println("cf2的结果="+cf2.get());
CompletableFuture.handle
跟whenComplete函数基本一致,区别在于handle的回调方法有返回值,必须要return一个值,且handle方法得到的CompletableFuture的执行结果与前一个CompletableFuture的执行结果无关
测试案例
@Test
public void test10() throws Exception {
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
if(true){
throw new RuntimeException("test");
}else{
return 1.2;
});
CompletableFuture<String> cf2=cf.handle((a,b)->{
if(b!=null){
log.error("cf执行异常,异常信息={}",b.getMessage());
}else{
log.info("cf执行正常,没有抛任何异常。且cf执行的结果={}",a);
if(b!=null){
return "run error";
}else{
return "run succ";
});
System.out.println("cf2的返回值="+cf2.get());
CompletableFuture.thenCombine
和CompletableFuture.thenAcceptBoth
和CompletableFuture.runAfterBoth
。
这三个方法都是将两个CompletableFuture组合起来,只有当那两个CompletableFuture都正常执行完了才会执行某个任务,区别在于,thenCombine会将两个任务的执行结果作为方法入参传递到指定方法中,且该方法有返回值;thenAcceptBoth同样将两个任务的执行结果作为方法入参,但是无返回值;runAfterBoth没有入参,也没有返回值。注意两个任务中只要有一个执行异常,则将该异常信息作为入参传递到这3个方法中。
@Test
public void test7() throws Exception {
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return 1.2;
});
CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
return 3.2;
});
CompletableFuture<Double> cf3=cf.thenCombine(cf2,(a,b)->{
log.info("thenCombine,a={},b={}",a,b);
return a+b;
});
CompletableFuture cf4=cf.thenAcceptBoth(cf2,(a,b)->{
log.info("thenAcceptBoth,a={},b={}",a,b);
});
CompletableFuture cf5=cf4.runAfterBoth(cf3,()->{
log.info("runAfterBoth,无入参,无返回值");
});
System.out.println("cf的返回结果="+cf.get());
System.out.println("cf2的返回结果="+cf2.get());
System.out.println("cf3的返回结果="+cf3.get());
System.out.println("cf4的返回结果="+cf4.get());
System.out.println("cf5的返回结果="+cf5.get());
CompletableFuture.applyToEither
和CompletableFuture. acceptEither
还有CompletableFuture. runAfterEither
。 这三个方法都是将两个CompletableFuture组合起来,只要其中一个CompletableFuture执行完了就会执行某个任务,其区别在于applyToEither会将已经执行完成的任务的执行结果作为方法入参,并有返回值;acceptEither同样将已经执行完成的任务的执行结果作为方法入参,但是没有返回值;runAfterEither没有方法入参,也没有返回值。注意两个任务中只要有一个执行异常,则将该异常信息作为指定任务的执行结果。
@Test
public void test8() throws Exception {
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
int i = random.nextInt()%10;
try {
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
log.info("cf执行完毕");
return 1.2;
});
CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
int i = random.nextInt()%10;
try {
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
log.info("cf2执行完毕");
return 3.2;
});
CompletableFuture<Double> cf3=cf.applyToEither(cf2,(result)->{
log.info("cf3开始执行了,接收到的result={},当前时间={}",result,LocalDateTime.now());
int i = random.nextInt()%10;
try {
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
log.info("cf3开始执行完毕");
return result;
});
CompletableFuture cf4=cf.acceptEither(cf2,(result)->{
log.info("cf4开始执行了,接收到的result={},当前时间={}",result,LocalDateTime.now());
int i = random.nextInt()%10;
try {
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
log.info("cf4开始执行完毕");
});
CompletableFuture cf5=cf4.runAfterEither(cf3,()->{
log.info("cf5开始执行了");
});
try {
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
测试结果:
CompletableFuture.thenCompose
这个函数跟CompletableFuture.thenApply
很相似。但是有点区别,thenApply()转换的是泛型中的类型,相当于将CompletableFuture<T>
转换生成新的CompletableFuture<U>
而thenCompose()用来连接两个CompletableFuture,是生成一个新的CompletableFuture。
@Test
public void test9() throws Exception {
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return 1.2;
});
CompletableFuture<String> cf2= cf.thenCompose((param)->{
log.info("param={}",param);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return "job3 test";
});
});
log.info("cf2的结果={}",cf2.get());
CompletableFuture.allOf
返回的CompletableFuture是多个任务都执行完成后才会执行,只要有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。
CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException("test");
});
CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
return 2.2;
});
CompletableFuture<Double> cf3 = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(1300);
} catch (InterruptedException e) {
return 3.2;
});
CompletableFuture cf4=CompletableFuture.allOf(cf,cf2,cf3).whenComplete((a,b)->{
if(b!=null){
log.error("cf,cf2,cf3中至少有一个任务出现了异常,异常信息={}",b.getMessage());
}else{
log.error("cf,cf2,cf3任务全部执行成功,a={}",a);
});
log.info("cf4执行完毕,结果={}",cf4.get());
CompletableFuture.anyOf
anyOf 的含义是只要有任意一个 CompletableFuture 结束,就可以做 接下来的事情,而无须像 AllOf 那样,等待所有的 CompletableFuture 结束。但由于每个 CompletableFuture 的返回值类型都可能不同,任意一个, 意味着无法判断是什么类型,所以 anyOf 的返回值是 CompletableFuture<Object>
类型
@Test
public void test11() throws Exception {
CompletableFuture<String> cf = CompletableFuture.supplyAsync(()->{
log.info("cf执行开始了");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
log.info("cf执行开始结束");
return "xiaoming";
});
CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(()->{
log.info("cf2执行开始了");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
log.info("cf2执行开始结束");
return 2.2;
});
CompletableFuture<Double> cf3 = CompletableFuture.supplyAsync(()->{
log.info("cf3执行开始了");
try {
Thread.sleep(1300);
} catch (InterruptedException e) {
log.info("cf3执行开始结束");
return 3.2;
});
CompletableFuture<Object> cf4=CompletableFuture.anyOf(cf,cf2,cf3).whenComplete((a,b)->{
if(b!=null){
log.info("cf4执行开始,a={},b={}",a,b.getMessage());
}else{
log.info("cf4执行开始,a={}",a);
});
log.info("cf4执行结果={}",cf4.get());
TimeUnit.SECONDS.sleep(10);
CompletableFuture默认使用ForkJoinPool.commonPool()线程池,如果机器是单核的,则默认使用ThreadPerTaskExecutor,该类是一个内部类,每次执行execute都会创建一个新线程
@SneakyThrows
private void test() {
Comp
letableFuture<String>
future =
Comp
letableFuture.supply
Async(() -> {
return "任务A";
}).then
ApplyAsync(s -> {
System.out.println(s);
return "任务B";
通过调用异步方法(方法后边加Async后缀),串联起来的CompletableFuture可以异步地执行(使用ForkJoinPool.commonPool())。
static void thenApplyAsyncExample() {
CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
assertTrue(Thread.currentThr
所谓异步调用其实就是实现一个可无需等待被调用函数的返回值而让操作继续运行的方法。在 Java 语言中,简单的讲就是另启一个线程来完成调用中的部分计算,使调用继续运行或返回,而不需要等待计算结果。但调用者仍需要取线程的计算结果。
JDK5新增了
Future接口,用于描述一个异步计算的结果。虽然
Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却...
static void thenApplyExample() {
CompletableFuture cf = CompletableFuture.completedFuture("message").thenApply(s -> {
assertFalse(Thread.currentThread().isDaemon());
本文是CompletableFuture类的功能和用例的指南- 作为Java 8 Concurrency API改进而引入。
2. Java中的异步计算
异步计算很难推理。通常我们希望将任何计算视为一系列步骤。但是在异步计算的情况下,表示为回调的动作往往分散在代码中或者深深地嵌套在彼此内部。当我们需要处理其中一个步骤中可能发生的错误时,情况变得更糟。
Future接口是Java 5中添加...
Java CompletableFuture继承了CompletionStage和Future接口。
CompletableFuture.thenApply继承自CompletionStage。
thenApply返回一个新的CompletionStage,当该阶段正常完成时,将使用该阶段的结果作为所提供函数的参数来执行该过程。
从Java文档中找到thenApply的方法声明。
<U> CompletionStage<U> thenApply(Function<? super
private ThreadPoolExecutor threadPoolExecutor;
CompletableFuture.supplyAsync(() -> {
做第一件事情;
return A;
},threadPoolExecutor).thenRun(()->{
private void test() {
CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
try {...
先来回顾下Future,Future是JDK1.5中添加的接口,主要功能为:但Future也有着非常明显的缺点:上面介绍了Future的缺点,这些问题都可以通过类解决,主要方法有:
可以看出,supply开头的两个方法是有返回值的,而run开头的两个方法是没有返回值的,至于第二个方法传入的Executor,这个在编码中可以自定义;
功能:当前任务正常完成以后,可将当前任务的返回值作为参数传给下一个任务;
执行任务A,任务A执行完成之后,将任务A返回值作为参数传入给任务B,打印结果为3:
以工作中常
CompletableFuture是Java 8引入的一种异步编程工具,它可以帮助我们更方便地处理异步任务和并发操作。下面是一些玩转CompletableFuture的方法和技巧:
1. 创建CompletableFuture对象:可以使用CompletableFuture的静态工厂方法,比如CompletableFuture.supplyAsync()创建一个带有返回值的CompletableFuture对象,CompletableFuture.runAsync()创建一个不带返回值的CompletableFuture对象。
2. 组合多个CompletableFuture:可以使用thenCompose()方法将多个CompletableFuture进行串行组合,也可以使用thenCombine()方法将多个CompletableFuture进行并行组合。
3. 异常处理:使用exceptionally()方法可以在CompletableFuture发生异常时进行处理,使用handle()方法可以对异常进行处理并返回一个默认值。
4. 超时处理:使用orTimeout()方法可以设置CompletableFuture的超时时间,如果在指定时间内任务没有完成,则会抛出TimeoutException。
5. 并行处理:使用allOf()方法可以并行执行多个CompletableFuture,并等待它们全部完成。
6. 异步回调:可以使用whenComplete()、handle()、exceptionally()等方法来注册异步回调函数,在任务完成时执行相应的操作。
7. 取消任务:使用completeExceptionally()方法可以取消CompletableFuture任务的执行。
这些只是CompletableFuture的一些常见用法和技巧,你可以根据具体的需求进一步探索和玩转CompletableFuture。希望对你有所帮助!
报SQL异常Parameter index out of range (1 > number of parameters, which is 0).
weixin_57295291:
解决:Linux下-bash: nohup: command not found或者bash: nohup: 未找到命令的问题
AbrahamCui:
高数复习笔记(同济 第七版 上下册)
烂人662: