一、jdk1.5Future接口
1.1 接口方法
- Future接口提供了异步获取执行结果的方法get()
- 取消异步执行方法cancel()
- 异步获取执行结果,设定超时时间,超时报错get(long timeout,TimeUnit timeUnit)
1.2 Future接口的不足
- 不支持进一步非阻塞调用,在通过异步调用执行方法时,没有提供回调函数,只能一直阻塞等到任务完成
- 不支持链式调用
- 不支持多个异步结果合并
- 不支持异常处理
- 我们想要获取执行结果只能使用get()阻塞式调用,或者使用循环判断isDone()再调用get()方法获取结果,耗费CPU资源
二、CompletableFuture
JDK1.8之后新值一个提供了繁多方法的类CompletableFuture,其提供了很多扩展功能,支持异步获取执行结果、任务合并、对执行结果再异步消费、多任务顺序执行、速度比较消费快速的等方法
2.1 异步获取执行结果
- get():任务执行异常会抛出异常ExecutionException,阻塞等待过程被打断会抛出InterrputedException
- get(long timeout,TimeUnit unit),阻塞超时抛出TimeoutException
- getNow(T valueIfAbsent),立即获取执行结果,如果没有则传出传入的默认值
- join(),不抛出异常
- complete(),返回异步是否执行完毕,如果传入的默认值结果为false则代表已经执行完成,获取到的是异步执行结果,否则拿到的是传入的默认值
2.2 任务合并
public <U,V> CompletableFuture<V> thenCombine(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn) {
return biApplyStage(null, other, fn);
}
用于两两任务完成后,将任务结果进行合并处理,先完成任务等待未完成任务执行结果
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 24, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {
return 25;
}, poolExecutor);
CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> {
return 50;
}, poolExecutor);
CompletableFuture<Integer> futureC = CompletableFuture.supplyAsync(() -> {
return 75;
}, poolExecutor);
CompletableFuture<Integer> combine = futureA.thenCombine(futureB, (resA, resB) -> {
return resA + resB;
}).thenCombine(futureC, (resSum, resC) -> {
return resSum + resC;
});
System.out.println(combine.get());
}
2.3 执行结果再异步消费
- thenRun(Runnable action),不关心前面任务的结果,也没有返回值
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 24, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 125;
}, poolExecutor);
future.thenRun(() -> {
System.out.println("执行后续逻辑");
});
poolExecutor.shutdown();
}
- thenAccept(Consumer action),接受前面的返回值,用于后续逻辑处理,处理完成不会有返回值
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 24, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 125;
}, poolExecutor);
future.thenAccept(res -> {
System.out.println("上一个程序执行结果为:" + res);
});
poolExecutor.shutdown();
}
- thenApply(Function fn),接受前面的返回值,后续处理完成之后,有返回值
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 24, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
return 125;
}, poolExecutor);
CompletableFuture<Integer> returnFuture = future.thenApply(res -> {
return res + 5;
});
System.out.println(returnFuture.get());
poolExecutor.shutdown();
}
2.4 多任务顺序执行
我们使用thenCompose()用于处理那些需要顺序执行的任务
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 24, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {
System.out.println("执行任务A,返回结果:" + 50);
return 50;
}, poolExecutor);
futureA.thenCompose(res -> {
return CompletableFuture.supplyAsync(() -> {
System.out.println("执行任务B,增加值:" + 75);
return 75 + res;
});
}).whenComplete((res, ex) -> System.out.println(res));
poolExecutor.shutdown();
}
2.5 任务速度比较,消费速度快的
public <U> CompletableFuture<U> applyToEither(
CompletionStage<? extends T> other, Function<? super T, U> fn) {
return orApplyStage(null, other, fn);
}
代码示例
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 24, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1024));
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("执行程序A,返回50");
return 50;
}, poolExecutor);
CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> {
System.out.println("程序B开始执行,返回75");
return 75;
}, poolExecutor);
future.applyToEither(futureB, res -> {
System.out.println("最终执行结果:" + res);
return res;
});
poolExecutor.shutdown();
}