学习内容
前言 :Future 接口 理论知识
定义了操作异步任务 执行一些方法, 比如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。
栗子 : 主任务 主线程 不能中断开启一个子线程, 让子线程 去执行耗时的任务。
对应的API
public class Test4 {
public static void main(String[] args) {
try {
MyThread2 t2 = new MyThread2();
FutureTask futureTask = new FutureTask<>(t2);
futureTask.get(); // 获取返回值 输出 this is call ()
Thread thread = new Thread(futureTask);
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Runnable 和 Callable 区别
* 1. 方法 不同
* 2. 返回值类型
* 3.方法会抛出异常
*/
class MyThread2 implements Callable<String> {
@Override
public String call() throws Exception {
return "this is call ()";
}
}
class MyThread implements Runnable {
@Override
public void run() {
}
}
缺点 :
- 使用 get 会阻塞 , 一旦调用get()方法求结果,如果计算机没有完成容易导致程序阻塞。
- isDone 不断轮询 使用 while(true) 会消耗cpu 效率
结论:Future 获取结果不是很友好,只能通过阻塞或者轮询方法获取结果。
CompletableFuture在Future 上的改进:
前言: get()方法在Future 计算完成之前会一直处在阻塞状态下,isDone()方法容易耗费CPU资源,阻塞的方式和异步编程的设计理念相违背,而轮询的方式会耗费无谓的CPU资源。因此,JDK8设计出CompletableFuture。
CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。
是什么:
- 在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture 的方法。
- 它可能代表一个明确完成的Future,也有可能代表一个完成阶段(CompletionStage ),它支持在计算完成以后触发一些函数或执行某些动作。
- 它实现了Future和CompletionStaqe接口
public class CompletableFuture implements Future, CompletionStage {}
completionstage
completionstage代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段
一个阶段的计算执行可以是一个function,consumer或者runable,比如:stage.thenapplyx>square()thenaccept
(x->system.out.print(x).thenrun(0)->system.out.println0)
.一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发
代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段,有些类似nx系统的管造分隔符传参数。
四个静态方法, 来创建一个异步任务
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
100,
200,
1,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>()
);
try {
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
try {
System.out.println(Thread.currentThread().getName() + ":come in ");
Thread.sleep(100);
int result = ThreadLocalRandom.current().nextInt(10);
System.out.println("结果 :" + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello supplyAsync()";
/**
*
* public CompletableFuture<T> whenComplete(
* BiConsumer<? super T, ? super Throwable> action) {
* return uniWhenCompleteStage(null, action);
} V 表示上一个步骤得出的结果 也就是 result
e 表示 是否异常
*/
}, threadPoolExecutor).whenComplete((v, e) -> {
if (e == null) {
System.out.println("finished");
}
/**
* public CompletableFuture<T> exceptionally(
* Function<Throwable, ? extends T> fn) {
* return uniExceptionallyStage(fn);
* }
* 程序出现了异常 会走这个分支
*/
}).exceptionally(e -> {
e.printStackTrace();
System.out.println("异常情况" + e.getCause() + "\t");
return null;
});
System.out.println(Thread.currentThread().getName() + "主线程 ");
} catch (Exception e) {
e.printStackTrace();
}finally {
threadPoolExecutor.shutdown();
}
优点
- 异步任务结束时,会自动回调某个对象的方法:
- completablefuture的优点 主线程设置好回调后,不再关心异步任务的执行,异步任务之间可以顺序执行
- 异步任务出错时,会自动回调某个对象的方法: