与Spring 3.0.6的@Async

时间:2016-10-26 14:31:43

标签: java spring multithreading spring-async

我正在尝试使用 @Async 注释实现异步调用。显然,由于它是一个遗留项目,Spring版本是3.0.6,所以它不支持更新的接口( AsyncConfigurer )和后来的Spring版本中引入的监听器。

目前, @Async 调用在发送电子邮件所需的方法上运行正常。调用代码调用该方法并返回以恢复正常控制。然后, @Async 调用将作为单独的线程调用。所有这一切都非常好,并达到了目的。

@Async 调用是一种方法,可以在应用程序中发送电子邮件。但是,有时会触发1000封电子邮件。我假设这会增加1000个左右的线程。这会不会导致具有如此多活动线程的应用程序出现问题?这些线程是否自行终止?在内存使用和堆空间方面,JVM会发生什么?

此外,我试图通过将该方法标记为 @Async 来尝试从另一个方法调用此方法,但看起来该线程未创建,并且控件实际上在那里等待完成该方法中的所有操作。为什么它有不同的行为?不知道为什么会这样。

提前致谢!

3 个答案:

答案 0 :(得分:1)

它产生了多少个线程以及如何排队以及如何定义taskExecutor bean。

此处的文档:http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#scheduling

答案 1 :(得分:1)

您的Emailtasks将首先存储在(默认为无限制)队列中。

  

默认情况下,队列是无限制的,但这很少是所需的配置,因为如果在所有池线程忙的情况下将足够的任务添加到该队列,则可能导致OutOfMemoryErrors。

如果您只使用Annotation,则spring将创建一个默认执行程序。此执行程序使用默认设置,您可以通过在配置文件或配置类中配置执行程序属性来更改这些设置:

<task:executor
        id="emailSenderExecutor"
        pool-size="5-25"
        queue-capacity="100"/>

然后在你的代码中:

@Async(value = "emailSenderExecutor")
public void sendEmail(Email email) {
    [...]
}

阅读更多内容以及如何配置执行程序:docs.spring.io

答案 2 :(得分:1)

<强> @Async: 可以在方法上提供@Async注释,以便异步调用该方法。换句话说,调用者将在调用时立即返回,并且该方法的实际执行将发生在已提交给Spring TaskExecutor的任务中。

  

@Async如何工作:

异步处理的这种行为是在运行时使用代理为您的类实现的。 当你的类的bean通过Spring注入到其他类时,Spring真的会注入代理。因此,调用代理的相关方法。

  

这不会导致应用程序出现如此多的直播问题   线程

您可以非常具体地定义任务执行程序配置。 例如如何配置任务执行程序(如果您使用spring xml配置)。

> <bean id="taskExecutor"
> class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
>     <property name="corePoolSize" value="5" />
>     <property name="maxPoolSize" value="10" />
>     <property name="queueCapacity" value="25" /> </bean>
  

这些线程是否自行终止?

这些线程由Spring容器管理。

  

JVM在内存使用和堆空间方面会发生什么?

显然,创建的代理数量越多,将消耗更多的堆内存。

  

为什么它有不同的行为?

我假设您在同一个类中创建了2个异步方法,并在另一个类中调用了一个异步方法。 所以当你从类中调用一个方法时,Spring AOP的局限性就是代理永远不会发挥作用,而是作为常规方法触发。