2016-10-26 34 views
2

我正在尝试使用@Async批注实现异步调用。显然,自从它是一个传统项目以来,Spring版本是3.0.6,所以它不支持较新的接口(AsyncConfigurer)以及后来的Spring版本中引入的侦听器。@Async with Spring 3.0.6

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

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

此外,我试图通过标志着方法@Async调用从另一种方法这种方法,但它看起来像没有创建线程和控制实际等待在那里完成该方法的所有操作。为什么它有不同的行为?不知道为什么会这样。

在此先感谢!

回答

1

它产生了多少线程以及如何排队取决于你如何定义taskExecutor bean。

文档浏览:http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#scheduling

+0

我还没有使用任务执行器。我没有在applicationContext.xml或任何spring文件中配置任何东西。 –

+0

有时候,应用程序的其他部分可以配置一个,而Async注释只是选择这些。 您可能需要显式配置ThreadPoolTask​​Executor bean,然后假设您在Spring 3中使用XML而不是以编程方式进行配置,请将您的Asynch支持绑定到执行器,如下所示: '' – PaulNUK

1

你Emailtasks将首先存储在一个(默认为无限制)队列。

默认情况下,队列是无界的,但是这是很少需要的配置,因为如果有足够的任务被添加到队列中,而所有池线程都很忙它可以导致OutOfMemoryError异常。

如果您仅使用注释,则默认执行程序将在spring中创建。此执行使用默认设置,您可以通过在您的配置文件或配置类配置执行人性质发生变化:

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

,然后在你的代码:

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

了解更多以及如何配置执行人: docs.spring.io

+0

我不太了解任务的执行者:执行者。我只提供了一个异步调用方法的注释。所有导致是一个独立执行的新线程,让控制器从此继续。我没有使用过任何执行器 –

+0

@ E2241我编辑了我的问题 – dit

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的局限性就是代理永远不会发挥作用,而是作为常规方法触发。