java multithreading spring asynchronous spring-4

java - Método asíncrono Spring llamado desde otro método asíncrono



multithreading asynchronous (1)

Estoy usando Spring 4 y he notado un comportamiento extraño ... si llamo a un método asíncrono varias veces desde un método de instancia normal, a todos se les llama en diferentes subprocesos y finalizan en momentos aleatorios. Pero si llamo varias veces un método asíncrono desde otro método asíncrono, entonces terminan en orden. Tengo algo como esto:

@Async public void nonAsyncMethod() { for (int i = 0; i < 30; i++) { asyncMethod(); } } @Async public void asyncMethod() { ... something here }

Estoy usando el ejecutor asíncrono predeterminado. ¿Debo usar uno diferente? Sin embargo, este ejecutor no reutiliza ningún hilo y comienza con otro cada vez, así que debería estar bien ... ¿Puede ser solo una coincidencia? Pero lo he intentado más de 10 veces y si vuelvo a ser no asíncrono para el primer método, terminan al azar.


Lo que estás describiendo es un escollo clásico de Spring AOP.

En resumen, para que Spring pueda proporcionar el comportamiento asíncrono que necesita para crear un proxy para su clase en tiempo de ejecución. El proxy hace lo que necesita hacer antes y / o después de llamar a su código. Pero en su caso, el mecanismo de proxy no se está aplicando para el segundo método.

Cuando un bean de su clase se inyecta a través de Spring en algún otro componente, Spring realmente inyecta el proxy en su lugar. Para ello se llama el método relevante del proxy. Sin embargo, cuando llama a un método desde dentro de la clase, las limitaciones de Spring AOP significan que el proxy nunca entra en juego, sino que se llama al método normal, sin funciones adicionales.

Es por eso que asyncMethod siempre se ejecuta en el mismo subproceso que el otro método en la misma clase que lo llamó.

Echa un vistazo a this excelente publicación de blog, así como a this parte de la documentación de Spring.

Hay algunas formas de solucionar el problema (ver this ) que no requieren que refactorice su código, pero si quiere que async funcione en ambos métodos sin importar qué, lo más simple que puede hacer es refactorizar el segundo método en otra clase. .