如何在Spring中正确使用@Async

时间:2015-11-30 08:52:46

标签: java spring spring-mvc asynchronous spring-boot

我对Spring的@Async注释以及如何正确使用它有疑问。假设我有这些方法:

@Async
public void test(String param1) {
    test2(param1, null);
}

@Async
public void test2(String param1, String param2) {
    test3(param1, param2, null);
}

@Async
public void test3(String param1, String param2, String param3) {
    // do some heavy work
}

我是否需要在所有三种方法上使用@Async才能异步调用它,或者它只能在test3上实际完成这项工作吗?

3 个答案:

答案 0 :(得分:3)

你确实只需要一种方法。仅仅因为在使用第一个@Async - 方法启动新线程之后,它与调用方法是异步的。

但这对你意味着什么,在很大程度上取决于你的例子应该说明的内容:

1)因此,在您通过{{1}调用@Asynctest1(String param1)时,test2的{​​{1}}就足够了}}

test3

请注意,方法2和3是私有的

2)但是,如果您的示例用于说明默认参数(Method chaining)的方法重载模式,则更复杂。然后,您需要在执行真实内容的方法中使用test1注释。因为您只想以异步方式执行实际执行,而不是每个链接步骤执行一次异步调用。

@Async
public void test1(String param1) {
    test2(param1, null);
}

private void test2(String param1, String param2) {
    test3(param1, param2, null);
}

private void test3(String param1, String param2, String param3) {
    // do something
}

请注意,所有方法仅以@Async命名(方法链式模式)

问题是,如果通过public void test(String param1) { test(param1, null); } public void test(String param1, String param2) { //this invocation runs async only when real AspectJ is used test(param1, param2, null); } @Async public void test(String param1, String param2, String param3) { // do something } 调用它,那么Spring(没有真正的AspectJ加载或编译时编织)将不会运行方法async()(参见{ {3}})

答案 1 :(得分:2)

我认为@Ralph涵盖了您的担忧。

但问题的名称是“如何在Spring中正确使用@Async”,我不得不提到:

您应该始终在Spring上下文中更改(或至少考虑更改)默认任务执行程序,或使用自定义任务执行程序。

Because:

  

默认情况下,SimpleAsyncTaskExecutor将用于处理异步   方法调用。

and:

  

注意:此实现不会重用线程!请考虑使用线程池TaskExecutor实现,尤其是   执行大量短期任务。

答案 2 :(得分:0)

仅在第三种方法@Async上使用test3是不够的,因为本地调用导致该对象未被代理,并且只有代理对象(从容器中拾取,例如使用@Autowired)异步调用

同时查看here