异步回调原理详解与实现

目录

FutureTask案例分析

1.FutureTask代码演示

public class FutureTaskTest {
    
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    

        Task task = new Task();

        //测试FutureTask的阻塞获取结果
        FutureTask<Integer> integerFutureTask = new FutureTask<>(task);

        Thread thread = new Thread(integerFutureTask);
        thread.start();

        //此处阻塞获取结果
        System.out.println(integerFutureTask.get());

        System.out.println("执行完成");
    }

}



class Task implements Callable<Integer>{
    
    

    @Override
    public Integer call() throws Exception {
    
    
        Thread.sleep(10000);
        return 100;
    }
}

2.FutureTask分析

优点:
 FutureTask是可以获取返回结果的一个线程任务,不像Runnable没有返回值,纯后端多线程任务
缺点:
 FutureTask的缺点也很明显,因为只有当需要同步返回的时候才会使用这个当做一个target,所以必须要等待线程执行完
 才能拿到执行结果,并且会阻塞主线程

FutureTask实现异步回调

1.代码自己实现异步回调功能

public class FutureTaskTest {
    
    

    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    

        Task task = new Task();

        //测试FutureTask的阻塞获取结果
        FutureTask<Integer> integerFutureTask = new FutureTask<>(task);

        Thread thread = new Thread(integerFutureTask);
        thread.start();

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        FutureTaskTools.callBack(integerFutureTask, new FutureTaskCallBack<Integer>() {
    
    
            @Override
            public Integer getResult(Integer integer) {
    
    
                System.out.println("执行结果:"+integer);
                return integer;
            }
        },executorService);

        System.out.println("执行完成");
    }

}

/**
 * 处理异步回调的工具类
 */
class FutureTaskTools{
    
    

    /**
     * futureTask的阻塞任务进行异步处理,丢到线程池中执行
     * @param futureTask
     * @param futureTaskCallBack
     * @param executorService
     */
    public static void  callBack(FutureTask futureTask,FutureTaskCallBack futureTaskCallBack,ExecutorService executorService){
    
    
        executorService.submit(new FutureResultTask(futureTaskCallBack,futureTask));
    }


    /**
     * 1.将futureTask的get阻塞方法封装为一个异步任务
     * 2.调用get成功之后,使用回调函数发生回调
     * @param <T>
     */
    private static final class FutureResultTask<T> implements Runnable {
    
    

        private FutureTaskCallBack<T> futureTaskCallBack;

        private FutureTask<T> futureTask;

        public FutureResultTask(FutureTaskCallBack<T> futureTaskCallBack, FutureTask<T> futureTask) {
    
    
            this.futureTaskCallBack = futureTaskCallBack;
            this.futureTask = futureTask;
        }

        @Override
        public void run() {
    
    
            try {
    
    
                //阻塞等待执行结果
                T t = futureTask.get();
                //回调,将结果反馈到主线程中
                futureTaskCallBack.getResult(t);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            } catch (ExecutionException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

/**
 * /事件回调接口,异步任务执行完后回调的类型
 * @param <T>
 */
interface FutureTaskCallBack<T>{
    
    

    T getResult(T t);

}

/**
 * 待执行的任务
 */
class Task implements Callable<Integer>{
    
    

    @Override
    public Integer call() throws Exception {
    
    
        Thread.sleep(10000);
        return 100;
    }
}

2.异步回调原理分析

1.FeatureTask获取结果的时候是阻塞的,直接丢到一个线程池中进行执行,这样可以保证不阻塞主线程,实现异步
2.FeatureTask是有返回结果的,我们需要包装一个回调对象,可以理解为Handler,当异步线程拿到结果,直接调用即可,实现回调

GUAVA实现异步回调

1.引入jar

<dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>29.0-jre</version>
</dependency>

2.使用guava异步回调代码演示

public class FutureTaskTest {
    
    

    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    

        Task task = new Task();

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
        ListenableFuture<Integer> submit = listeningExecutorService.submit(task);

        Futures.addCallback(submit, new FutureCallback<Integer>() {
    
    
            @Override
            public void onSuccess(@Nullable Integer integer) {
    
    
                System.out.println("执行结果:"+integer);
            }

            @Override
            public void onFailure(Throwable throwable) {
    
    

            }
        },executorService);


        System.out.println("执行完成");
    }

}

/**
 * 待执行的任务
 */
class Task implements Callable<Integer>{
    
    

    @Override
    public Integer call() throws Exception {
    
    
        Thread.sleep(10000);
        return 100;
    }
}

3.原理分析

1.guava的实现原理和之前上一个我们自己实现异步回调原理是一样的
2.Futures相当于我们的FutureTaskTools,将需要的阻塞获取结果对象,进行打包为一个异步任务,丢到线程池
3.ListenableFuture相当于FutureTask,用户阻塞获取同步结果,这个对象可以阻塞获取结果
4.FutureCallback相当于FutureTaskCallBack,用于回调,当异步任务执行完,使用的回调对象

猜你喜欢

转载自blog.csdn.net/weixin_38312719/article/details/108255493