12、多线程的异步回调

引用学习(狂神说)

介绍

线程执行的时候,不想要等待怎么办。

多线程的异步处理,与同步处理相比,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其他线程处理完成,并回调通知该线程。

客户端与服务器端有 ajax 可以实现异步。

而我们 Java 也有 Future接口实现同步。

如何使用?

查看官方文档

在JUC包下可以找到Future接口,我们需要掌握的就是CompletableFutrue类,一般会使用它。

 

常用方法

  1. 没有返回值的异步操作

    • 一个是直接运行线程,一个是通过Executor执行

  2. 又返回值的异步调用

    • 一个是直接运行线程,一个是通过Executor执行

  3. 返回报错的信息

  4. 等待结果的返回

测试代码

没有返回值的异步回调

  • CompletableFuture.runAsync(),执行异步任务,没有返回值

package com.zxh.future;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;


/**
 * 异步回调:CompletablFuture
 * 1、可以异步执行
 * 2、成功回调
 * 3、失败回调
 */
public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 没有返回值的异步回调
        // Void类,就是void关键字,没有返回值
        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("1111");
        completableFuture.get();    // 获取阻塞执行结果

    }
}

如果只是通过Thread创建线程,如果有上面的阻塞等待的情况,也会先输出111,但是无法自由控制,它是由CPU控制的。

执行成功:有返回值的异步操作

  • CompletableFuture.supplyAsync(),执行异步任务,并且有返回值

package com.zxh.future;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;


/**
 * 异步回调:CompletablFuture
 * 1、可以异步执行
 * 2、成功回调
 * 3、失败回调
 */
public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*
            有返回值的回调,supplyAsync():里面的参数是Suplier供给型函数接口,有输出,没有输入
          */
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "supplyAsync=> 有返回值");    // 表示执行了异步任务
            return 1024;    //直接返回 1024
        });

        /*
            BiConsumer:是消费型接口的改变版,可以传递2个参数 void accept(T t, U u);
                这两个参数,t表示:正常的返回结果,u表示:错误信息
            exceptionally方法:参数为Function<Throwable, ? extends T> fn),可以有输入也可以有返回值
                如果有错误就将错误输入,输出
            get()方法:获取异步回调返回的参数
         */
        System.out.println(completableFuture.whenComplete((t, u)->{
            System.out.println("t=>" + t);
            System.out.println("u=>" + u);
        }).exceptionally((e) -> {
            System.out.println(e.getMessage());
            return 500; // 可以获取到错误的返回值
        }).get());

    }
}

执行失败:模拟除数为0错误

package com.zxh.future;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;


/**
 * 异步回调:CompletablFuture
 * 1、可以异步执行
 * 2、成功回调
 * 3、失败回调
 */
public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*
            有返回值的回调,supplyAsync():里面的参数是Suplier供给型函数接口,有输出,没有输入
          */
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "supplyAsync=> 有返回值");    // 表示执行了异步任务
            int i = 1/0;    // 制造异常
            return 1024;    //直接返回 1024
        });

        /*
            whenComplete(BiConsumer<? super T, ? super Throwable> action):
                获取该线程的返回值和异常信息,第一个参数是返回值,第二个参数是异常信息
                BiConsumer:是消费型接口的改变版,可以传递2个参数 void accept(T t, U u);
                    这两个参数,t表示:正常的返回结果,u表示:错误信息
            exceptionally(Function<Throwable, ? extends T> fn)):
                参数为Function:可以有输入也可以有返回值
                如果出现错误,将错误对象传入函数接口,输出错误,并自定义返回值
            get()方法:获取异步回调返回的参数
         */
        System.out.println(completableFuture.whenComplete((t, u)->{
            System.out.println("t=>" + t);  // 正常的返回结果
            System.out.println("u=>" + u);  // 错误信息
        }).exceptionally((e) -> {
            System.out.println(e.getMessage()); // 输出错误信息
            return 500; // 可以获取到错误的返回值
        }).get());

    }
}

 

 接下来的小节都是层层递进的。

 

posted @ 2020-06-01 10:49  忘忧山的兰木  阅读(969)  评论(0编辑  收藏  举报
她只是想吃这个而已啊……这一定是她非常爱吃的,我居然连如此细微的幸福也夺走了……
Hide
Switch
Save