自从java8引入了Stream、函数式编程、CompletableFuture等特性之后,给我们码代码提供了不少酷炫的操作。从JDK1.5开始我们就可以通过Future接口实现异步,主要是创建一个线程池,然后提交Runnable或者Callable的任务。然后可以用get来获取返回结果(执行完毕才会返回),传统回调最大的问题就是不能将控制流分离到不同的事件处理器中。而CompletableFuture弥补了缺陷。本文主要讲CompletableFuture相关的特性。
根据下面这行代码可以看出CompletableFuture实现了Future,CompletionStage。说明CompletableFuture既有保留了Future的特性,又通过CompletableFuture进行了扩展。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
1.函数式接口
观察CompletableFuture代码,可以看出方法参数都是函数式接口,这个比较切合jdk1.8的编码风格。因此,我们可以先了解一下何为函数式编程。函数式编程就是通过lambda表达式进行简化编码。符合函数编程的接口叫函数式接口,函数式接口有一个特性,就是只能有一个抽象方法,在jdk1.8中函数式接口除了仅有的一个抽象方法,还可以拥有default缺省方法或者static静态方法。以下介绍几个函数式接口。
1.Function<T, R>:一个输入一个返回,stream中的map方法的入参就是该函数式接口
该接口的核心抽象方法:R apply(T t);调用该方法的输入参数是T,返回结果是R。示例如下:
public static void main(String[] args){
Function<String,Integer> function = a->{
return Integer.parseInt(a);
};
System.out.println(function.apply("5"));
}
2.Supplier<T>:没有输入,有一个返回
该接口的核心抽象的方法:T get();示例如下:
Supplier<Integer> supplier = ()->{
return 5;
};
System.out.println(supplier.get());
3.Predicate<T>:一个输入参数,返回布尔值,stream中该函数式接口作为filter的入参。
该接口的核心抽象的方法:boolean test(T t);示例如下:
Predicate<Integer> predicate = a->{
return a==5;
};
System.out.println(predicate.test(5));
4.Consumer<T>:一个输入,没有返回,stream中的foreach使用该接口作为输入。
该接口的核心的方法是:void accept(T t);示例如下:
Consumer<Integer> consumer = a->{
System.out.println(a);
};
consumer.accept(5);
5.BiConsumer<T, U>:两个输入,没有输出。同Consumer<T>,区别在于输入参数个数不同。
示例如下:
BiConsumer<Integer,Integer> biConsumer = (a,b)->{
System.out.println(a+b);
};
biConsumer.accept(5,3);
6.BiFunction<T, U, R>:两个输入,有输出。同Function<T,R>,区别在于输入参数个数不同。
BiFunction<Integer,Integer,String> biFunction = (a,b)->{
return String.valueOf(a+b);
};
System.out.println(biFunction.apply(4,5));
2.CompletableFuture实战
由于CompletableFuture实现了Future接口和CompletionStage接口。所以保持了两个接口的特性的基础上进行了扩展,CompletableFuture类的主要特性方法如下:
1.创建实例
创建实例的方法如下:
#异步,提供一个supplier对象生成CompletableFuture对象
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
#异步,提供一个supplier对象生成CompletableFuture对象,该异步线程在指定
#线程池消费
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
Executor executor) {
return asyncSupplyStage(screenExecutor(executor), supplier);
}
public static CompletableFuture<Void> runAsync(Runnable runnable) {
return asyncRunStage(asyncPool, runnable);
}
public static CompletableFuture<Void> runAsync(Runnable runnable,
Executor executor) {
return asyncRunStage(screenExecutor(executor), runnable);
}
#同步,给定一个值封装成CompletableFuture对象
public static <U> CompletableFuture<U> completedFuture(U value) {
return new CompletableFuture<U>((value == null) ? NIL : value);
}
2.串行执行
#同步
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);
public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenRun(Runnable action);
public <U> CompletionStage<U> thenCompose
(Function<? super T, ? extends CompletionStage<U>> fn);
#异步
public <U> CompletionStage<U> thenApplyAsync
(Function<? super T,? extends U> fn);
public <U> CompletionStage<U> thenApplyAsync
(Function<? super T,? extends U> fn,
Executor executor);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,
Executor executor);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,
Executor executor);
public <U> CompletionStage<U> thenComposeAsync
(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletionStage<U> thenComposeAsync
(Function<? super T, ? extends CompletionStage<U>> fn,
Executor executor);
3.AND汇聚关系
#同步
public <U,V> CompletionStage<V> thenCombine
(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn);
public <U> CompletionStage<Void> thenAcceptBoth
(CompletionStage<? extends U> other,
#异步
public <U,V> CompletionStage<V> thenCombineAsync
(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync
(CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn,
Executor executor);
public <U> CompletionStage<Void> thenAcceptBothAsync
(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action);
public <U> CompletionStage<Void> thenAcceptBothAsync
(CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action,
Executor executor);
4.OR汇聚关系
#同步
public <U> CompletionStage<U> applyToEither
(CompletionStage<? extends T> other,
Function<? super T, U> fn);
public CompletionStage<Void> acceptEither
(CompletionStage<? extends T> other,
Consumer<? super T> action);
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,
Runnable action);
#异步
public <U> CompletionStage<U> applyToEitherAsync
(CompletionStage<? extends T> other,
Function<? super T, U> fn);
public <U> CompletionStage<U> applyToEitherAsync
(CompletionStage<? extends T> other,
Function<? super T, U> fn,
Executor executor);
public CompletionStage<Void> acceptEitherAsync
(CompletionStage<? extends T> other,
Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync
(CompletionStage<? extends T> other,
Consumer<? super T> action,
Executor executor);
public CompletionStage<Void> runAfterEitherAsync
(CompletionStage<?> other,
Runnable action);
public CompletionStage<Void> runAfterEitherAsync
(CompletionStage<?> other,
Runnable action,
Executor executor);
5示例实战
实体类student
public class Student {
private String name;
private int age;
private String stuId;
public Student(String name,int age,String stuId){
this.name=name;
this.age=age;
this.stuId=stuId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStuId() {
return stuId;
}
public void setStuId(String stuId) {
this.stuId = stuId;
}
public String toString(){
return "student[name="+name+",age="+age+",stuId="+stuId+"]";
}
}
工具类StudentUtil
public class StudentUtil {
public static String getName(Student student){
return "completableFuture:"+student.getName();
}
}
实例:以下将上述常见的方法进行举例介绍
public class UserTestDemo {
private static Map<String,User> map = new ConcurrentHashMap<>();
private static List<User> list = new ArrayList<>();
static {
map.put("1000",new User("Bob",24));
map.put("1001",new User("Curry",34));
map.put("1002",new User("Amy",35));
list.add(map.get("1000"));
list.add(map.get("1001"));
list.add(map.get("1002"));
}
public static CompletableFuture<User> getUser(String id){
//创建一个future
CompletableFuture<User> completableFuture = CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
return map.get(id);
});
return completableFuture;
}
public static CompletableFuture<List<User>> combine(CompletableFuture<User> userCompletableFuture,String id){
//合并
return getUser(id).thenCombine(userCompletableFuture,(a,b)->{
List<User> list = new ArrayList<>();
list.add(a);
list.add(b);
return list;
});
}
public static void main(String[] args){
//创建一个future
CompletableFuture<User> userCompletableFuture = getUser("1000");
System.out.println(userCompletableFuture.isDone());
//合并
CompletableFuture<List<User>> listCompletableFuture = combine(userCompletableFuture,"1001");
System.out.println("thenCombine:"+listCompletableFuture.join());
userCompletableFuture.thenAccept(r-> {
System.out.println(r.getName()+" is "+r.getAge());
});
System.out.println(userCompletableFuture.isDone());
//合并 and Executor
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
CompletableFuture<List<User>> listCompletableFutureExecutor = userCompletableFuture.thenCombineAsync(getUser("1001"),(a,b)->{
List<User> list = new ArrayList<>();
list.add(a);
list.add(b);
return list;
},executor);
System.out.println("executorAndCombine:"+listCompletableFutureExecutor.join());
//or
CompletableFuture<User> orCompletableFuture = getUser("1001").applyToEitherAsync(getUser("1000"),r->{
return r;
});
System.out.println("orUser:"+orCompletableFuture.join());
CompletableFuture<User> userCompletableFuture1 = getUser("1001");
//apply
CompletableFuture<Student> studentCompletableFuture = userCompletableFuture1.thenApplyAsync(r->{
return new Student(r.getName(),r.getAge(),"1000000");
});
System.out.println("apply:"+studentCompletableFuture.join());
System.out.println("apply:"+studentCompletableFuture.join());
System.out.println("apply:"+studentCompletableFuture.isDone());
CompletableFuture<Student> studentCompletableFutureAsync = userCompletableFuture1.thenApplyAsync(r->{
try {
Thread.sleep(10);
System.out.println("aaaa");
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Student(r.getName(),r.getAge(),"1000000");
});
System.out.println(studentCompletableFuture.join());
System.out.println("abcd");
//map and thenCompose
List<CompletableFuture<String>> userNameList = list.stream()
.map(r->CompletableFuture.supplyAsync(()->r.toStudent(String.valueOf(new Random().nextInt(1000)))))
.map(r->r.thenComposeAsync(student->CompletableFuture.supplyAsync(()-> StudentUtil.getName(student))))
.collect(Collectors.toList());
List<String> nameList = userNameList.stream().map(CompletableFuture::join).collect(Collectors.toList());
System.out.println("thenCompose:"+nameList);
}
}