持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,[点击查看活动详情]
上篇文章讲述了future的使用,但是不知道大家有没有发现future的缺点就是在获取返回值的时候get是阻塞的,且如果某个任务,比如任务二的执行需要获取任务一的结果才能执行,你就会发现future就不够灵活。
此时completableFuture就体现出他的强大了,completableFuture实现了future接口和CompletionStage接口,使得其具有future的全部功能,且扩展了更加强大的功能,同时也有多种api能够灵活组合使用。
下面来看下completableFuture的实际使用
ExecutorService executorService = Executors.newFixedThreadPool(5);
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
log.info("current thread name :" + Thread.currentThread().getName());
//休眠两秒
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
int nextInt = ThreadLocalRandom.current().nextInt(10);
return nextInt;
});
首先创建了一个线程池,然后使用completableFuture的supplyAsync创建了一个带有返回的任务执行。
- get:获取数据,有方法重载,传入时间,超过指定时间抛出timeout超时异常,不传那就是阻塞等待获取,上面是认为阻塞2秒钟了,使用get设置1秒获取,执行结果如下图:
使用不设置超时的get来获取数据,且将我们的线程池设置为completableFuture的执行线程池,注意看上面图片的执行线程名称,是completablefuture默认的futureTask线程池,当CPU核数大于1时默认启用,如果我们不传如自定义线程池的话,执行结果如下图:
可以看到在等待2秒后获取到了结果,且执行线程名称换成了我自定义的线程池
- getNow:获取当前任务此刻的执行结果,如果任务还在执行中或者为空那么就返回自定义的值返回,执行结果如下图:
- join:这个方法也是获取结果但是不需要抛出异常,其他和get一样,执行结果如下图:
可以看到join并没有try cache异常,但是还是需要等待2秒获取结果。
- isCompletedExceptionally:是否异常的,改下代码,在任务执行的时候人为的抛出异常,然后对比为抛出异常和抛出异常的区别,可以发现如果在执行过程中发送异常那么isCompletedExceptionally返回true,没抛出异常返回false,可以用于区分当前任务是否执行正常,执行结果如下:
这些只是产品买票了completableFuture对于future的api的实现和扩展,只是其常用基础api的一部分,更加丰富的组合api主要来自于另外一个接口CompletionStage,后续的文章将会继续讲解