IT技术篇

Spring框架中的异步执行

2020-01-05  本文已影响0人  Java并发

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

上一篇 下一篇

猜你喜欢

热点阅读