美文网首页IT技术篇
Spring框架中的异步执行

Spring框架中的异步执行

作者: Java并发 | 来源:发表于2020-01-05 21:10 被阅读0次

    一、Spring框架中的异步执行

    在Spring Framework中分别使用TaskExecutor和TaskScheduler接口提供异步执行和任务调度的抽象,本节我们着重讲解基于TaskExecutor支撑的的注解@Async如何实现异步处理的。

    二、 @Async注解异步处理原理

    在Spring中可以在方法上添加@Async注释,以便异步调用该方法。换句话说,调用者将在调用含有@Async注释的方法时立即返回,并且该方法的实际执行将发生在Spring TaskExecutor异步处理器线程中。需要注意的是该注解@Async默认是不会解析的,SpringBoot中需要加上@EnableAsync来启动。

    下面我们看如何使用@Async注解进行异步处理,如下代码:

    @Async
        public void dosomthingAsync() {
    
            System.out.println("--dosomthingAsync begin---");
            // 模拟异步处理
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("--dosomthingAsync end---");
        }
    

    如上代码在方法dosomthingAsync上添加了@Async的注解,所以当我们调用dosomthingAsync方法时候,该方法会马上返回。

    另外使用@Async可以有返回值,因为它们将在运行时由调用者以“正常”方式调用,而不是由容器管理的调度任务TaskExecutor自动调用。例如,以下是使用@Async注解的合法方法:

    @Component
    public class AsyncTask {
    ...
        @Async
        public CompletableFuture<String> dosomthingAsyncFuture() {
    
            System.out.println("--dosomthingAsync begin---");
            CompletableFuture<String> future = new CompletableFuture<String>();
    
            // 模拟异步处理
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            future.complete("ok");
            System.out.println("--dosomthingAsync end---");
    
            return future;
        }
    }
    

    如上代码调用该方法后,该方法会马上返回一个CompletableFuture对象,如果你一直持有这个CompletableFuture对象,那么等dosomthingAsyncFuture内业务处理异步处理完毕后,就可以从dosomthingAsyncFuture的get()方法获取到执行结果。

    那么Spring框架是如何做到我们dosomthingAsyncFuture时候会马上返回一个CompletableFuture那?其实其对该类进行了代理,经过代理后的上面的方法类似于:

    public class AsynTaskProxy {
    
        public AsyncTask getAsyncTask() {
            return asyncTask;
        }
    
        public void setAsyncTask(AsyncTask asyncTask) {
            this.asyncTask = asyncTask;
        }
    
        private AsyncTask asyncTask;
    
        private TaskExecutor executor = new SimpleAsyncTaskExecutor();
    
        public CompletableFuture<String> dosomthingAsyncFuture() {
    
            return CompletableFuture.supplyAsync(new Supplier<String>() {
    
                @Override
                public String get() {
                    try {
                        return asyncTask.dosomthingAsyncFuture().get();
                    } catch (Throwable e) {
                        throw new CompletionException(e);
                    }
                }
            },executor);
        }
    }
    

    Spring会对AsyncTask类使用类似的AsynTaskProxy进行代理,并且会把AsynTask的实例注入到AsynTaskProxy内部,当我们调用AsynTask的dosomthingAsyncFuture方法时候,实际调用的是AsynTaskProxy的dosomthingAsyncFuture方法,后者则使用 CompletableFuture.supplyAsync开启了一个异步任务(其马上返回一个 CompletableFuture对象),并且使用默认的SimpleAsyncTaskExecutor线程池做为异步处理线程,然后异步任务内在具体调用了 AsyncTask实例的dosomthingAsyncFuture方法,并且在返回的future上获取执行结果。

    相关文章

      网友评论

        本文标题:Spring框架中的异步执行

        本文链接:https://www.haomeiwen.com/subject/hkbcactx.html