本文是自己的学习笔记,主要参考资料如下
https://www.cnblogs.com/dolphin0520/p/3920407.html
JavaSE文档
https://blog.csdn.net/ThinkWon/article/details/102508721
- 1、Overview
- 2、重要参数
- 3、主要方法
- 3.1、创建实例,获取返回值
- 3.2、线程执行顺序相关
1、Overview
CompletableFuture
可以处理任务的执行顺序,比如A执行结束后再开始B,或者A和B同时进行,两者都结束后再开始C。
2、重要参数
CompletableFuture
中有三个重要参数,他们的作用和Thread
中的run
方法一样,用来定义线程的行为。
他们的不同点知识入参和返回结果的不同。
Supplier<U>
:没有入参,有返回结果Consumer<T>
:有入参,没有返回结果Function<T,U>
:有入参,有返回结果
比如我们写一个线程任务,参数是Supplier
,那就不能传参,但是有返回值,就像callable()
方法一样。
CompletableFuture<String> a = CompletableFuture.supplyAsync(() -> {
System.out.println("第一个异步任务开始执行");
System.out.println("第一个异步任务执行结束");
return "supply example";
});
System.out.println(a.join());
Thread.sleep(5000L);
返回结果
3、主要方法
3.1、创建实例,获取返回值
一般用静态方法创建实例,有下面两种创建实例的方法,区别是是否有返回值。
supplyAsync()
:传入Supplier
类型,可以有返回值。runAsync()
:传入Runable
类型,无返回值。
这里以supplyAsync
为例
public static void supplysync() throws Exception{
// 不指定线程池,默认用ForkJoinPool,这个线程池的线程都是守护线程
CompletableFuture<Void> result = CompletableFuture.supplyAsync(() -> {
System.out.println("异步任务开始执行");
System.out.println("异步任务执行结束");
return "返回执行结果";
});
System.out.println(result.join());
// get()和join()一样,但是join()自己处理了异常,get()需要处理异常
System.out.println(result.get());
Thread.sleep(20000L);
}
要注意,supplyAsync()
和runAsync()
都两个重载方法,即是否传入线程池。
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
如果不传入线程池,那默认使用ForkJoinPool
作为线程池处理线程,而这个线程池的线程全是守护线程,所以测试代码中必须让主线程沉睡一会,免得主线程过早结束导致守护线程跟着结束让我们看不到测试结果。
3.2、线程执行顺序相关
CompletableFuture
提供了下面几种控制线程执行顺序的方法,他们各自都有多个重载方法,这里不一一列举了。
下面两条规则比较普遍。
-
几乎所有的方法都有个同名加
Async
后缀的方法,比如thenSupply()
有一个thenSupplyAsync()
,这两者没有功能上的不同,只是后者可以传线程池。 -
一些方法有加
Both
后缀,比如runAfter()
有个runAfterBoth()
,前者表示等某个线程结束后这个线程再运行,后者则是等多个线程都结束后这个线程再运行。 -
在我之后执行:
thenApply()
,thenAccept()
,thenRun()
,thenApplyAsync()
等都是,只是能否传参,是否有返回值和使用的线程池不同而已。 -
在我之前:
runAfter()
。 -
和我同时:
thenCombine()
-
有一个结束我就开始:
applyToEither()
public static void thenSupply() throws Exception{
CompletableFuture<String> a = CompletableFuture.supplyAsync(() -> {
System.out.println("第一个异步任务开始执行");
System.out.println("第一个异步任务执行结束");
return "supply example";
}).thenApply(b -> {
System.out.println("第二个异步任务开始执行");
System.out.println("第二个异步任务执行结束");
return "thenApply example";
});
System.out.println(a.join());
Thread.sleep(5000L);
}