异步回调
1.异步回调
说到异步回调我们第一个想到的肯定是ajax技术,它是客户端和服务器之间的异步回调技术,而在java线程中也可以异步通信,就是Futrue技术。
Futrue接口是对将来的某个事件进行建模,其通过CompletableFuture进行实现。
CompletableFuture是Future接口的实现方法,是当两个或者多个线程试图调用complete方法的时候,只会有一个成功,并且其可以执行异步方法,方法如下图:
public static CompletableFuture<Void> runAsync(Runnable runnable,
Executor executor) {
return asyncRunStage(screenExecutor(executor), runnable);
}
2.Futrue接口实现的异步回调
2.1 步骤
2.1.1 首先创建Futrue接口的实现类CompletableFuture,指定其泛型
2.1.2 异步执行,异步执行分为两种,一种是没有返回值的执行方法runAsync,一种是有返回值的执行方法supplyAsync
2.1.2.1 可以设置成功回调方法,在有返回值的supplyAsync方法返回后,如果成功进行相关业务操作;
2.1.2.3 可以设置失败回调方法,在有返回值的supplyAsync方法返回后,如果失败则进行获取异常,错误的返回结果等操作;
3.CompletableFuture实现类的使用
3.1没有返回值的runAsync异步回调方法
注:Void为void的包装器类可以作为CompletableFuture的泛型,表示没有返回值。
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"runAsync void");
});
System.out.println("查看是否延迟执行。。。");
completableFuture.get();//获取阻塞执行结果
}
执行结果:
查看是否延迟执行。。。
ForkJoinPool.commonPool-worker-9runAsync void
如果我们将延迟去掉后,我们会发现谁先来就谁先执行,符合异步操作。
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
System.out.println(Thread.currentThread().getName()+"runAsync void");
});
completableFuture.get();//获取阻塞执行结果
System.out.println("查看是否延迟执行。。。");
}
执行结果:
ForkJoinPool.commonPool-worker-9runAsync void
查看是否延迟执行。。。
3.2 有返回值的异步回调方法<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
可以看出参数是一个供给型回调函数Supplier<U> (有没参数,只有返回值),因此可以优化为CompletableFuture.supplyAsync(()-{return 根据前面的设定的泛型设置此处的返回值});,此处返回的为成功的回调。
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return asyncSupplyStage(asyncPool, supplier);
}
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
列举一个栗子:设置好成功的回调方法和失败的回调方法,通过下面的代码我们观察下成功和失败的回调都是怎么展示的。
public static void main(String[] args) {
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
System.out.println(Thread.currentThread().getName()+"supplyAsync Integer");
//int i = 19/0;
return 1024;
});
completableFuture.whenComplete((t,u)->{
System.out.println("t= "+t);//正常的返回结果 t= 1024 u= null
System.out.println("u= "+u);//错误的信息 t= null u= java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
}).exceptionally((e)->{
//打印堆栈信息
// return e.printStackTrace();
//打印详细信息
System.out.println(e.getMessage());//java.lang.ArithmeticException: / by zero
return 999;//可以获取错误的返回结果
});
}
3.2.1 成功的回调
成功的回调方法whenComplete中的参数是一个BiConsumer函数式接口参数,长得很像Consumer接口,是一个消费型函数式接口的变种类型(传入参数T,返回参数U,没有返回值),通过lambda表示的可以优化为.whenComplete((t,u)->{相关业务代码})。
public CompletableFuture<T> whenComplete(
BiConsumer<? super T, ? super Throwable> action) {
return uniWhenCompleteStage(null, action);
}
public interface BiConsumer<T, U> {
/**
* Performs this operation on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
*/
void accept(T t, U u);
3.2.2 失败的回调
失败的回调方法exceptionally方法参数为Throwable异常类,Exception和Error都继承了该类,其用来定义所有可以作为异常被抛出来的类(很牛逼),而返回值则是自定义的CompletableFuture的泛型,所以通过lambda表达式简化操作为.exceptionally((异常类的参数)->{return CompletableFuture中自定义的泛型})。
public CompletableFuture<T> exceptionally(
Function<Throwable, ? extends T> fn) {
return uniExceptionallyStage(fn);
}
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
- 点赞
- 收藏
- 关注作者
评论(0)