CompletableFuture是Java8提供的一个并发类,方法很多,使用相对复杂。
使用场景:多个线程需要并行或者串行等发杂场景。
先示例一下CompletableFuture的简单场景,上一篇中讲到一个场景是,A和B并行执行,其中结果给C再去执行。
使用CompletableFuture会更简便易于理解。
CompletableFutureDemo.java
package com.example.demo.concurrent.completablefuture;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@Slf4j
public class CompletableFutureDemo {
public static void main(String[] args) {
//如果是runAsync方法,则不需要return
CompletableFuture completableFuture = CompletableFuture.supplyAsync(()->{
log.info("执行线程-----开始----");
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
log.info("执行线程-----处理数据中----无操作--无返回--");
log.info("执行线程-----结束----");
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Result("飞翔的咩咩","1");
});
//需要返回结果
CompletableFuture completableFutureA = CompletableFuture.supplyAsync(()->{
log.info("执行线程A-----开始----");
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
log.info("执行线程A-----处理数据中-----");
log.info("执行线程A-----结束----");
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Result("飞翔的咩咩A","25");
});
//需要返回结果
CompletableFuture completableFutureB = CompletableFuture.supplyAsync(()->{
log.info("执行线程B-----开始----");
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
log.info("执行线程B-----数据处理中:----");
log.info("执行线程B-----结束----");
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Result("飞翔的咩咩B","25");
});
//C会等待A和B结束后执行。
CompletableFuture completableFutureC = completableFutureA.thenCombine(completableFutureB,(resultA,resultB)->{
log.info("执行线程保存处理结果-----开始----");
List<Result> resultList = new ArrayList<Result>();
Result rsA = (Result) resultA;
Result rsB = (Result) resultB;
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
rsA.setAge(String.valueOf(Integer.parseInt(rsA.getAge())+1));
rsB.setAge(String.valueOf(Integer.parseInt(rsB.getAge())+1));
log.info("执行线程保存处理结果-----resultA,age+1后为:{}----",rsA.toString());
log.info("执行线程保存处理结果-----resultB,age+1后为:{}----",rsB.toString());
resultList.add(rsA);
resultList.add(rsB);
log.info("执行线程保存处理结果-----结束----");
} catch (InterruptedException e) {
e.printStackTrace();
}
return resultList;
});
System.out.println(completableFutureC.join());
}
}
执行结果为:这个逻辑是,A和B异步执行,C等待他们的结果,并且都在age上加1.再输出
00:03:25.836 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程B-----开始----
00:03:25.836 [ForkJoinPool.commonPool-worker-9] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程-----开始----
00:03:25.836 [ForkJoinPool.commonPool-worker-2] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程A-----开始----
00:03:25.838 [ForkJoinPool.commonPool-worker-2] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程A-----处理数据中-----
00:03:25.838 [ForkJoinPool.commonPool-worker-2] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程A-----结束----
00:03:26.848 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程B-----数据处理中:----
00:03:26.848 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程B-----结束----
00:03:26.848 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程保存处理结果-----开始----
00:03:27.848 [ForkJoinPool.commonPool-worker-9] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程-----处理数据中----无操作--无返回--
00:03:27.848 [ForkJoinPool.commonPool-worker-9] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程-----结束----
00:03:27.868 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程保存处理结果-----resultA,age+1后为:Result{name='飞翔的咩咩A', age='26'}----
00:03:27.868 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程保存处理结果-----resultB,age+1后为:Result{name='飞翔的咩咩B', age='26'}----
00:03:27.868 [ForkJoinPool.commonPool-worker-11] INFO com.example.demo.concurrent.completablefuture.CompletableFutureDemo1 - 执行线程保存处理结果-----结束----
[Result{name='飞翔的咩咩A', age='26'}, Result{name='飞翔的咩咩B', age='26'}]
CompletableFuture功能很强大,实现了Future<T>和 CompletionStage<T>,实现Future<T>能获取异步结果。实现CompletionStage<T>能使用很多强大功能。
在这里我们仅使用两个方法:
CompletableFuture<U> supplyAsync(Supplier<U> supplier)
CompletableFuture<V> thenCombine( CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
其中supplyAsync(Supplier<U> supplier)是有返回的,不需要返回可以用
CompletableFuture<Void> runAsync(Runnable runnable)
我们看一下runAsync源码
/**
* Returns a new CompletableFuture that is asynchronously completed
* by a task running in the {@link ForkJoinPool#commonPool()} after
* it runs the given action.
*
* @param runnable the action to run before completing the
* returned CompletableFuture
* @return the new CompletableFuture
*/
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return asyncRunStage(asyncPool, runnable);
}
因为没有传线程池就使用了默认的ForkJoinPool.commonPool(),默认是创建CPU核数的线程池大小,有耗时任务时可能造成线程不够。建议自定义线程池,避免互相干扰。