在JDK8之前,我们使用的Java多线程变成,主要是 Thread+Runnable 来完成,但是这种方式有个弊端就是没有返回值。如果想要返回值怎么办呢,大多数人就会想到 Callable + Thread
的方式来获取到返回值。
通过上面的类继承关系图可以知道 CompletableFuture
实现了 Future
接口和 CompletionStage
。因此 CompletableFuture是对 Futrue的功能增强包含了Future的功能。从继承的另一个 CompletionStage
的名称来看完成阶段性的接口。
CompletableFuture的核心用途:
CompletableFuture类实现了Future和CompletionStage接口,相当于一个Task编排工具
Future
CompletionStage
当前的Task到底由那个Thread执行,使用的不好可能会有性能问题, 根据CompletableFuture
的方法命名可以掌握
方法API
//无返回值,默认使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码
public static CompletableFuture<Void> runAsync(Runnable runnable)
//无返回值,可以自定义线程池
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
//有返回值,默认使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
//有返回值,可以自定义线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
//如果返回值没有返回,一直阻塞
V get()
//设置等待超时的时间
V get(long timeout,Timeout unit);
//有返回值就返回, 线程抛出异常就返回设置的默认值
T getNow(T defaultValue);
//方法无返回值,当前任务正常完成以后执行,当前任务的执行结果可以作为下一任务的输入参数
thenAccept
//方法有返回值,当前任务正常完成以后执行,当前任务的执行的结果会作为下一任务的输入参数
thenApply
//对不关心上一步的计算结果,执行下一个操作
thenRun
(1)supplyAsync方法实战,有返回值,默认使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。
public static void testCompletableFuture1() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
return "lixiang";
});
System.out.println(future.get());
}
(2)runAsync方法实战,无返回值
public static void testCompletableFuture2() throws ExecutionException, InterruptedException {
CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
System.out.println("runAsync方法执行。。。");
});
System.out.println(future.get());
}
(3)thenApply 组合调度,能拿到上步执行的结果,并且当前执行完有任务返回值的
public static void testCompletableFuture3() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
System.out.println("supplyAsync方法执行。。。");
return "lixiang";
}).thenApply((ele)->{
System.out.println("thenApply方法执行。。。,拿到上一步的执行结果:"+ele);
return ele + " is a java工程师";
});
System.out.println(future.get());
}
(4)thenAccept 组合调度,能拿到上步执行的结果,当前执行完无任务返回值的
public static void testCompletableFuture4() throws ExecutionException, InterruptedException {
CompletableFuture<Void> future = CompletableFuture.supplyAsync(()->{
System.out.println("supplyAsync方法执行。。。");
return "lixiang";
}).thenAccept((ele)->{
System.out.println("thenAccept方法执行。。。,拿到上一步的执行结果:"+ele);
});
System.out.println(future.get());
}
需求
thenCompose
(1)编写商品类
@Data
public class Product {
private int id;
private String title;
private String detail;
}
(2)模拟商品service
public class ProductService {
private static final Map<Integer,String> map = new HashMap<>();
static {
map.put(1,"iphone14");
map.put(2,"iphone 蓝牙耳机");
map.put(3,"Mac Book Pro-详情图内容");
map.put(4,"小香风深蓝色大衣");
map.put(5,"清热解火菊花茶");
map.put(6,"补肝养肾枸杞大枣茶");
map.put(7,"颈椎病康复指南");
}
public String getById(int id){
try {
Thread.sleep(1000);
System.out.println("ProductService#getById方法运行线程:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return map.get(id);
}
}
(3)模拟商品详情service
public class ProductDetailService {
private static final Map<Integer,String> map = new HashMap<>();
static {
map.put(1,"iphone14-详情图内容");
map.put(2,"iphone 蓝牙耳机-详情图内容");
map.put(3,"Mac Book Pro-详情图内容");
map.put(4,"小香风深蓝色大衣-详情图内容");
map.put(5,"清热解火菊花茶-详情图内容");
map.put(6,"补肝养肾枸杞大枣茶-详情图内容");
map.put(7,"颈椎病康复指南-详情图内容");
}
public String getById(int id){
try {
Thread.sleep(1000);
System.out.println("DetailService # getById方法运行线程:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return map.get(id);
}
}
(4)测试方法,正常用thenApply,需要get两次
public static void test1() throws ExecutionException, InterruptedException {
ProductService productService = new ProductService();
ProductDetailService productDetailService = new ProductDetailService();
//第一步异步 ,第二部异步
CompletableFuture<CompletableFuture<Product>> future = CompletableFuture.supplyAsync(() -> {
Product product = new Product();
String title = productService.getById(1);
product.setId(product.getId());
product.setTitle(title);
return product;
}).thenApply(product -> CompletableFuture.supplyAsync(() -> {
String detail = productDetailService.getById(1);
product.setDetail(detail);
return product;
}));
//这块 获取 商品信息要get两次
System.out.println("获取商品信息:"+future.get().get());
}
(5)测试方法,用thenCompose,只需要get一次即可
public static void test2() throws ExecutionException, InterruptedException {
ProductService productService = new ProductService();
ProductDetailService productDetailService = new ProductDetailService();
//第一步异步 ,第二部异步
CompletableFuture<Product> compose = CompletableFuture.supplyAsync(() -> {
Product product = new Product();
String title = productService.getById(1);
product.setId(product.getId());
product.setTitle(title);
return product;
}).thenCompose(product -> CompletableFuture.supplyAsync(() -> {
String detail = productDetailService.getById(1);
product.setDetail(detail);
return product;
}));
//这块 获取 商品信息要get两次
System.out.println("获取商品信息:"+compose.get());
}
需求
thenCombine
编码实战
public static void test3() throws ExecutionException, InterruptedException {
ProductService productService = new ProductService();
ProductDetailService detailService = new ProductDetailService();
int id = 1;
//第1个任务
CompletableFuture<Product> baseProductFuture = CompletableFuture.supplyAsync(() -> {
String title = productService.getById(id);
Product product = new Product();
product.setTitle(title);
product.setId(id);
return product;
});
//第2个任务
CompletableFuture<Product> detailProductFuture = CompletableFuture.supplyAsync(() -> {
String detail = detailService.getById(id);
Product product = new Product();
product.setDetail(detail);
product.setId(id);
return product;
});
CompletableFuture<Product> compose = baseProductFuture.thenCombine(detailProductFuture,
(base, detail) -> {
base.setDetail(detail.getDetail());
return base;
});
System.out.println(compose.get());
}
public static void test3() throws ExecutionException, InterruptedException {
ProductService productService = new ProductService();
ProductDetailService detailService = new ProductDetailService();
int id = 1;
//第1个任务
CompletableFuture<Product> baseProductFuture = CompletableFuture.supplyAsync(() -> {
String title = productService.getById(id);
Product product = new Product();
product.setTitle(title);
product.setId(id);
return product;
});
//第2个任务
CompletableFuture<Product> detailProductFuture = CompletableFuture.supplyAsync(() -> {
String detail = detailService.getById(id);
Product product = new Product();
product.setDetail(detail);
product.setId(id);
return product;
});
CompletableFuture<Void> acceptBoth = baseProductFuture.thenAcceptBoth(detailProductFuture, (base, detail) -> {
base.setDetail(detail.getDetail());
System.out.println(base);
});
System.out.println(acceptBoth.get());
}
背景
(1)allOf编码实战
public static void testAllOf() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("future1执行完成");
return "future1执行完成";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("future2执行完成");
return "future2执行完成";
});
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("future3执行完成");
return "future3执行完成";
});
CompletableFuture<Void> all = CompletableFuture.allOf(future1, future2, future3);
//阻塞,直到所有任务结束。
System.out.println(Thread.currentThread().getName() + ":" + LocalDateTime.now() + ":阻塞");
//调用join方法等待全部任务完成
all.join();
if (all.isDone()) {
//一个需要耗时2秒,一个需要耗时3秒,只有当最长的耗时3秒的完成后,才会结束。
System.out.println("全部任务执行完成");
}
System.out.println(Thread.currentThread().getName() + ":" + LocalDateTime.now() + ":阻塞结束");
}
(2)anyOf编码实战
public static void testAnyOf() throws Exception {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("future1执行完成");
return "future1执行完成";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("future2执行完成");
return "future2执行完成";
});
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("future3执行完成");
return "future3执行完成";
});
CompletableFuture<Object> any = CompletableFuture.anyOf(future1, future2, future3);
//阻塞,最快任务执行完成 任务结束。
System.out.println(Thread.currentThread().getName() + ":" + LocalDateTime.now() + ":阻塞");
//调用join方法等待最快的一个任务执行
any.join();
if (any.isDone()) {
//一个需要耗时2秒,一个需要耗时3秒,一个耗时5秒 当最短的完成则会结束
System.out.println(any.get()+"任务执行完成");
}
System.out.println(Thread.currentThread().getName() + ":" + LocalDateTime.now() + ":阻塞结束");
}