使用场景
一般来说,当我们调用复杂的逻辑运算的方法时,如果采取顺序执行的方式,那么主线程就会被严重堵塞,从而大大影响到代码的执行效率。
想要解决这个问题,其实也很简单,只要为复杂的任务代码专门创建一个线程去异步执行就行。
详解
CompletableFuture源码中有四个静态方法用来执行异步任务:
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){..}
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor){..}
public static CompletableFuture<Void> runAsync(Runnable runnable){..}
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor){..}
run开头的两个方法,用于执行没有返回值的任务,因为它的入参是Runnable对象,而supply开头的方法显然是执行有返回值的任务了,至于方法的入参,第一个参数是传入执行的方法,主要是迎合了编程式函数的概念,第二个参数是传入一个线程池对象,用于管理线程,如果没有传入自定义的Executor对象将会默认使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码.在实际使用中,一般我们使用自己创建的线程池对象来作为参数传入使用,这样速度会快些。
大多数时,我们的业务需求都是需要执行有返回值的方法。
使用案例
1、执行异步任务
# 闯入一个匿名函数
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//....执行任务
return "hello";}, executor)
2、获取执行结果的几个方法
V get();
V get(long timeout,Timeout unit);
T getNow(T defaultValue);
上面两个方法是Future中的实现方式,get()会堵塞当前的线程,这就造成了一个问题,如果执行线程迟迟没有返回数据,get()会一直等待下去,因此,第二个get()方法可以设置等待的时间。
getNow()方法比较有意思,表示当有了返回结果时会返回结果,如果异步线程抛了异常会返回自己设置的默认值。
3、完成案例
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 返回的结果我们要声明,例如返回的是String
CompletableFuture<String> future = CompletableFuture.supplyAsync( () -> {return "Hello World";});
// 线程如果没完成,会一直堵塞在这
System.out.println( future.get());
}
}
4、结果
扫描二维码关注公众号,回复:
13294209 查看本文章
