- 一.CompletableFuture简介
- 二.CompletableFuture简单入门使用
- 1.创建对象
- 2.代码演示-无返回值类型
- 3.代码演示-有返回值类型
- 三.通用演示,传入回调函数,减少阻塞
- 四.总结.
为了满足Java在处理异步任务的一些不足,比如说对返回值获取不友好等,在1.8版本推出了CompletableFuture,它实现了Future和CompletionStage接口,拥有Futrue的全部功能,并拥有更加强大的异步回调,执行级联任务等等优点.
二.CompletableFuture简单入门使用 1.创建对象对于一般Java对象来说,最常见得就是直接new一个对象,但是CompletableFuture还是有点特别得,我们可以看到文档中已经说明,通过构造器会创建一个不完整得CompletableFuture对象.所以是不推荐使用空参构造方法来创建一个CompletableFuture对象得.
那要怎样获得这个对象呢?我们可以通过两组,四个方法进行获取.
这里需要注意Executor(线程池)得参数说明:
并且这里得ForkJoinPool.commonPool()创建得线程是守护线程(不理解守护线程的,可以看一下这个用户线程和守护线程的区别),这一点在第三节中会证明.
方法:CompletableFuture.runAsync()
使用自带得线程池(注意自带得是守护线程)
//当我们传入任务返回对象得时候,线程任务已经开始执行了
//使用自带得线程池(注意自带得是守护线程)
CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName());
});
//completableFuture 实现了Future, CompletionStage 接口,自然也会有Future得get()方法
System.out.println(completableFuture.get());
输出值:
使用自定义得线程池(默认用户线程)
ExecutorService executorService = Executors.newFixedThreadPool(3);
CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName());
},executorService);
//completableFuture 实现了Future, CompletionStage 接口,自然也会有Future得get()方法
System.out.println(completableFuture.get());
//使用线程池,记得进行关闭
executorService.shutdown();
输出值:
方法:CompletableFuture.supplyAsync
这里直接演示用自定义线程池得方法.
ExecutorService executorService = Executors.newFixedThreadPool(3);
CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
return "hello supplyAsync";
}, executorService);
//completableFuture 实现了Future, CompletionStage 接口,自然也会有Future得get()方法
System.out.println(completableFuture.get());
//使用线程池,记得进行关闭
executorService.shutdown();
输出结果:
我们知道CompletableFuture拥有比Future更强大的功能,能够减少阻塞和轮询.
我们可以传入一个回调函数,当异步任务完成得时候,自动执行回调方法.
举例:使用自带线程池:
CompletableFuturecompletableFuture = CompletableFuture.supplyAsync(() -> { System.out.println("开始执行异步任务...这个任务预计耗时1s"); System.out.println("执行异步任务线程为:"+Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "hello supplyAsync"; }).whenComplete((result,e)->{ System.out.println("异步任务已经执行完毕...获取结果:"+result); }).exceptionally((e) -> { e.printStackTrace(); System.out.println("出现异常:"+e.getCause()); //出现异常后返回得结果 return null; }); System.out.println("主线程开始忙其他得事情...");
输出结果:
细心得同学可能已经发现有问题了,程序并没有输出返回结果,直接就结束了,这是为什么呢?
因为我们使用的是自带得线程池,还记得前面说自带得线程池创建出来的线程都是守护线程吗,这里就体现出来得,因为main线程先于异步任务线程执行完毕,此时JVM中已没有用户线程了,所以守护线程自动被关闭.
所以我们需要改进一下,使用我们自定义得线程池,改进代码如下:
ExecutorService executorService = Executors.newFixedThreadPool(3);
CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("开始执行异步任务...这个任务预计耗时1s");
System.out.println("执行异步任务线程为:"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello supplyAsync";
},executorService).whenComplete((result,e)->{
System.out.println("异步任务已经执行完毕...获取结果:"+result);
}).exceptionally((e) -> {
e.printStackTrace();
System.out.println("出现异常:"+e.getCause());
//出现异常后返回得结果
return null;
});
System.out.println("主线程开始忙其他得事情...");
executorService.shutdown();
输出结果:
通过以上小练习我们能够知道CompletableFuture是具有如下这些优点的.



