1、前言
学习java基础时候多线程使用我们首先学习的 Runable
、Future
、 Thread
、ExecutorService
、Callable
等相关类,在我们日常工作或者学习中有些场景并不满足我们需求,JDK8引入了一个新的类 CompletableFuture
来解决之前得问题, CompletableFuture
实现了 Future
接口和 CompletionStage
。因此 CompletableFuture是对 Futrue的功能增强包含了Future的功能。从继承的另一个 CompletionStage
的名称来看完成阶段性的接口,接下来了解一下 CompletableFuture
的一些基本情况以及使用和注意事项。
2、CompletableFuture使用
CompletableFuture提供了几十种方法,辅助我们的异步任务场景。这些方法包括创建异步任务、任务异步回调、多个任务组合处理等方面,JDK8设计出CompletableFuture。CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。
自定义线城池,一下代码都会使用到
static ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
int count = 1;
@Override
public Thread newThread(Runnable runnable) {
return new Thread(runnable, "completableFuture-executor-" + count++);
}
});
2.1创建异步任务
-
runAsync 用于构建一个没有入参也没有出参的任务;
-
supplyAsync 用于构建一个没有入参但是有出参的任务
runAsync和supplyAsync可以指定线程池,如果不指定,则使用ForkJoinPool的commonPool线程池
先看源码
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return asyncRunStage(asyncPool, runnable);
}
public static CompletableFuture<Void> runAsync(Runnable runnable,
Executor executor) {
return asyncRunStage(screenExecutor(executor), runnable);
}
runAsync执行CompletableFuture任务,没有返回值。
/**
* runAsync执行CompletableFuture任务,没有返回值。
*/
public static void runAsyncExample() throws ExecutionException, InterruptedException {
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步线程执行执行结束");
});
System.out.println("异步线程执行状态" + completableFuture.isDone());
System.out.println("主线程正在执行");
System.out.println("异步线程执行状态" + completableFuture.isDone());
System.out.println(completableFuture.get());
}
执行结果
异步线程执行状态false
completableFuture-当前线程名称:ForkJoinPool.commonPool-worker-9
异步线程执行执行结束
null
supplyAsync执行CompletableFuture任务,支持返回值-使用自定义线城池
public static void supplyAsyncExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1001);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
System.out.println("异步线程执行执行结束");
return "msg-异步线程执行结束";
}, executor);
System.out.println("主线程-------supplyAsyncExample-----正在执行");
System.out.println(completableFuture.join());
executor.shutdown(); // 线程池需要关闭
}
执行结果
主线程-------supplyAsyncExample-----正在执行
completableFuture2-当前线程名称:completableFuture-executor-1
异步线程执行执行结束
msg-异步线程执行结束
2.2任务异步回调
2.2.1 thenRun/thenRunAsync
不关心上一个任务的执行返回结果,无参数,无返回值
CompletableFuture的thenRun方法,通俗点讲就是,做完第一个任务后,再做第二个任务。某个任务执行完成后,执行回调方法;但是前后两个任务没有参数传递,第二个任务也没有返回值
如果你执行第一个任务的时候,传入了一个自定义线程池:
- 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池。
- 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池
public CompletableFuture<Void> thenRun(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action);
thenRun代码
public static void thenRunExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1001);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步线程执行执行结束,当前线程"+Thread.currentThread().getName());
return "msg-异步线程执行结束";
}, executor);
System.out.println("主线程-------thenRunExample-----正在执行1");
CompletableFuture<Void> voidCompletableFuture = completableFuture.thenRun(() -> {
System.out.println("thenRunExample----正在执行第二个任务,当前线程"+Thread.currentThread().getName());
});
System.out.println("主线程-------thenRunExample-----正在执行2");
System.out.println(voidCompletableFuture.get());
executor.shutdown(); // 线程池需要关闭
}
执行结果
主线程-------thenRunExample-----正在执行1
主线程-------thenRunExample-----正在执行2
异步线程执行执行结束,当前线程completableFuture-executor-1
thenRunExample----正在执行第二个任务,当前线程completableFuture-executor-1
null
thenRunAsync代码-异步使用自定义线城池
public static void thenRunAsyncExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {