Spring框架中的异步执行

  • Post author:
  • Post category:其他


一、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上获取执行结果。

更深入的细节读者可以翻看AsyncExecutionInterceptor代码进行研究。

640?wx_fmt=gif


——图书推荐——

640?wx_fmt=png

——关注本号——

640?wx_fmt=png



版权声明:本文为m0_37055174原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。