这个completableFuture是JDK1.8版本新引入的类。下面是这个类。实现了俩接口。本身是个class。这个是Future的实现类。
使用completionStage接口去支持完成时触发的函数和操作。
一个completetableFuture就代表了一个任务。他能用Future的方法。还能做一些之前说的executorService配合futures做不了的。
之前future需要等待isDone为true才能知道任务跑完了。或者就是用get方法调用的时候会出现阻塞。而使用completableFuture的使用就可以用then,when等等操作来防止以上的阻塞和轮询isDone的现象出现
那就先介绍一下Future和Callable借口
代码:
public class FutureDemo {
public static void main(String[] args) throws Exception {
// 创建实现了Callable接口的实例
CallableDemo callableDemo = new CallableDemo();
// 于实现了Future接口的实现类 来接收返回的结果 我们一般用FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(callableDemo);
// 运行该线程
new Thread(futureTask).start();
// 获取结果
// 有两种方式
// 1. get
/*
* 如果线程没有执行完结果
* 这里会出现阻塞
*/
Integer integer = futureTask.get();
System.out.println("integer = " + integer);
// -----------------------我是华丽的分割线----------------------
// 2.isDone
// 创建实现了Callable接口的实例
CallableDemo callableDemo1 = new CallableDemo();
// 于实现了Future接口的实现类 来接收返回的结果 我们一般用FutureTask
FutureTask<Integer> futureTask1 = new FutureTask<>(callableDemo1);
// 运行该线程
new Thread(futureTask1).start();
// 判读线程
while (!futureTask.isDone()) {
TimeUnit.SECONDS.sleep(1);
}
Integer integer1 = futureTask.get();
System.out.println("integer = " + integer1);
}
}
/**
* 1. 实现Callable可以很值一个泛型 这个泛型就是方法的返回值 并且这个方法可以抛出异常
* 2. 执行callable方式 需要FutureTask实现类 支持 用于接收运算结果 FutureTask是 Future接口的实现类
*/
class CallableDemo implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
return sum;
}
}
CompletableFuture: 相比上面的方法不需要轮循 或 阻塞 在异步方法执行完成 再去执行另一个方法
总结一下优点:
·异步任务结束时,会自动回调某个对象的方法
·异步任务出错时,会自动回调某个对象的方法
·主线程设置好回调后,不再关心异步任务的执行
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建一个CompletableFuture CompletableFuture.supplyAsync异步的 他的参数是一个 Supplier函数式借口 提供一个子任务
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
int i = 10 / 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
return "执行完成 lamdba 执行完成";
});
// 子任务执行成功 回调给方法 参数是一个 Consumer的 函数式接口
cf.thenAccept(result -> {
System.out.println("子任务执行成功");
System.out.println("result = " + result);
});
// 子任务执行成功失败 回调这个方法 参数是一个 Function函数式借口
cf.exceptionally(e -> {
System.out.println("e = " + e.getMessage());
return "子任务执行成功失败";
});
cf.join();
}
穿行执行多个CompletableFuture
public static void main(String[] args) throws Exception {
// 创建一个CompletableFuture CompletableFuture.supplyAsync异步的 他的参数是一个 Supplier函数式借口 提供一个子任务
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "执行完成 lamdba 执行完成 一号";
});
CompletableFuture<String> cf1 = cf.thenApplyAsync((result) -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return result + " | 执行完成 lamdba 执行完成 二号";
});
// 子任务执行成功 回调给方法 参数是一个 Consumer的 函数式接口
cf1.thenAccept(result -> {
System.out.println("子任务执行成功");
System.out.println("result = " + result);
});
cf1.join();
}
并行执行多个CompletableFuture
anyOf
连个必须都执行成功 一个执行失败就 执行exceptionally 方法 哪一个先执行成功 使用哪一个
public static void main(String[] args) throws Exception {
// 创建一个CompletableFuture CompletableFuture.supplyAsync异步的 他的参数是一个 Supplier函数式借口 提供一个子任务
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
return "执行完成 lamdba 执行完成 一号";
});
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(0);
int i = 10 / 0;
} catch (InterruptedException e) {
throw new RuntimeException("");
}
return " | 执行完成 lamdba 执行完成 二号";
});
CompletableFuture<Object> cf2 = CompletableFuture.anyOf(cf, cf1);
// 子任务执行成功 回调给方法 参数是一个 Consumer的 函数式接口
cf2.thenAccept(result -> {
System.out.println("子任务执行成功");
System.out.println("result = " + result);
});
// 子任务执行成功失败 回调这个方法 参数是一个 Function函数式借口
cf2.exceptionally(e -> {
System.out.println("e = " + e.getMessage());
throw new RuntimeException("出现异常了");
});
cf2.join();
}
allOf
连个必须都执行成功 一个执行失败就 执行exceptionally 方法
最后的CompletableFuture 的泛型必须是 Void
public static void main(String[] args) throws Exception {
// 创建一个CompletableFuture CompletableFuture.supplyAsync异步的 他的参数是一个 Supplier函数式借口 提供一个子任务
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
return "执行完成 lamdba 执行完成 一号";
});
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(0);
} catch (InterruptedException e) {
throw new RuntimeException("");
}
return " | 执行完成 lamdba 执行完成 二号";
});
//
CompletableFuture<Void> cf2 = CompletableFuture.allOf(cf, cf1);
// 子任务执行成功 回调给方法 参数是一个 Consumer的 函数式接口
cf2.thenAccept(result -> {
System.out.println("子任务执行成功");
System.out.println("result = " + result);
});
// 子任务执行成功失败 回调这个方法 参数是一个 Function函数式借口
cf2.exceptionally(e -> {
System.out.println("e = " + e.getMessage());
throw new RuntimeException("出现异常了");
});
cf2.join();
}
CompletableFuture的命名规则:
xxx():继续在已有的线程中执行
xxxAsync():Executor的新线程执行
CompletableFuture对象可以指定异步处理流程:
thenAccept()处理正常结果
exceptional()处理异常结果
thenApplyAsync()用于串行化另一个CompletableFuture
anyOf / allOf用于并行化两个CompletableFuture