CompletableFuture的简单使用
简述CompletableFuture
CompletableFuture既可以看作是多线程,也可以看作是异步任务。
CompletableFuture是Java 8中引入的一个类,它提供了一种简单、灵活和强大的方式来处理异步操作。它允许你在等待一个异步操作完成时执行其他代码,并且可以使用回调函数或组合多个CompletableFuture来处理结果。这些特性使得CompletableFuture非常适合处理IO密集型或CPU密集型的任务。
在实现上,CompletableFuture通常会使用多线程来执行任务。当你调用CompletableFuture的异步方法时,它会将任务提交给线程池中的一个线程来执行。这样就可以避免阻塞主线程,提高程序的并发性和响应速度。
因此,可以说CompletableFuture既包含了多线程的特性(通过线程池来执行任务),又包含了异步任务的特性(允许在等待IO完成时执行其他代码)。
创建一个线程池
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture没有返回值的用法
没有返回值的异步任务,使用自己的线程池执行异步任务,如果不添加executor,那么使用的是默认的线程池。
CompletableFuture.runAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("i = " + i);
},executor);
CompletableFuture有返回值的用法
创建一个有返回值的异步任务,如果链式调用handle方法完成异步任务结束的操作,接收值为异步任务的返回值和异常;如果链式调用whenComplete方法,任务完成后的感知,如果存在异常返回future为null,异常名,成功正常显示future值;如果链式调用exceptionally方法,感知到异常将默认值返回。
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("i = " + i);
return i;
}, executor)
// 方法完成后的处理
.handle((res,exception) -> {
if (res != null){
return res * 2;
}
if (exception != null){
return 1;
}
return 0;
});
// // 完成后的感知,如果存在异常返回future为null,异常名,成功正常显示future值
// .whenComplete((res, exception) -> {
// System.out.println("结果是" + res + "和异常" + exception);
// })
// // 感知到异常将默认值返回
// .exceptionally((throwable) -> {
// System.out.println("默认值为0");
// return 0;
// });
// 打印出future的结果
System.out.println("future.get() = " + future.get());
CompletableFuture的线程串行化
创建一个有返回值的异步任务,链式调用thenRunAsync方法来将线程串行化,此方法不能获取到上一步的结果,无返回值,加Async新开一个线程,否则用上一个异步任务的线程;链式调用thenAcceptAsync方法,能获取到上一步的结果,无返回值;链式调用thenApplyAsync方法,能获取到上一步的结果,有返回值,加Async新开一个线程,否则用上一个线程。
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("i = " + i);
return i;
}, executor)
// 不能获取到上一步的结果,无返回值,加Async新开一个线程,否则用上一个线程
// .thenRunAsync(() -> {
// System.out.println("任务2启动");
// });
// 能获取到上一步的结果,无返回值,加Async新开一个线程,否则用上一个线程
// .thenAcceptAsync((res) -> {
// System.out.println("上一个任务的返回值 = " + res);
// })
// 能获取到上一步的结果,有返回值,加Async新开一个线程,否则用上一个线程
.thenApplyAsync((res) -> {
System.out.println("上一个任务的返回值 = " + res);
return res * 2;
});
// 打印出future1的结果
System.out.println("future1.get() = " + future.get());
CompletableFuture的双任务组合
创建两个有返回值的异步任务,使用其中的一个异步任务点击调用runAfterEitherAsync方法,传入第二个异步任务,当其中一个任务完成后执行lambda表达式中的代码;acceptEitherAsync方法能接受上面传来的返回值,applyToEitherAsync方法能够接受返回值并将自己的返回值return。
// 双任务有一个完成后执行
CompletableFuture<Integer> future5 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
System.out.println("任务1开始");
int i = 10 / 2;
System.out.println("i = " + i);
return i;
}, executor);
CompletableFuture<Integer> future6 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
System.out.println("任务2开始");
int i = 10 / 2;
System.out.println("i = " + i);
return i;
}, executor);
// 两任务有一个完成就执行
// 不接收返回值
future5.runAfterEitherAsync(future6,()->{
System.out.println("任务3开始");
},executor);
// 接收返回值
future5.acceptEitherAsync(future6,(res)->{
System.out.println("任务3开始" + res);
},executor);
// 接受返回值并返回值
future5.applyToEitherAsync(future6,(res)->{
System.out.println("任务3开始" + res);
return res;
},executor);
CompletableFuture的多任务组合
创建三个异步任务,调用allOf方法等待所有线程结束,使用get方法进行阻塞,anyOf方法则是等其中任意的的线程结束。
// 多任务组合
CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
System.out.println("查询商品图片信息");
return "msg";
}, executor);
CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
System.out.println("查询商品图片信息");
return "msg";
}, executor);
CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread().getId());
System.out.println("查询商品图片信息");
return "msg";
}, executor);
// 等所有的线程结束,get方法进行阻塞
CompletableFuture.allOf(futureImg, futureAttr, futureDesc).get();
// 等其中任意的的线程结束,get方法进行阻塞
CompletableFuture.anyOf(futureImg, futureAttr, futureDesc).get();