Get it on Google Play

Formación Spring: Programación asíncrona con Spring

25-04-2016
 
Async

Async

A partir del éxito del post del otro día “Activando tareas periódicamente con Spring” aprovecho para escribir este de un tema muy parecido. Ejecutar métodos asíncronamente en Spring.

Ejecutar métodos de manera asíncrona nos permite no parar el proceso mientras se ejecuta otra acción. Por ejemplo, en una aplicación web que procesa vídeo, nos permite que cuando el usuario nos sube el vídeo este se procese en segundo plano i así nosotros devolver una respuesta rápida ‘Estamos procesando tu vídeo’.

Spring nos ofrece una manera también muy simple de hacer esto:

Inicializar la aplicación

Al igual que hacíamos con los métodos que se ejecutaban periódicamente debemos activar la funcionalidad al declarar la aplicación(Con la anotación @EnableAsync):


@SpringBootApplication
@EnableAsync
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

Crear Servicio con los métodos que se ejecutarán asíncronamente

Después ya podemos declarar nuestros servicios que se ejecutarán de manera asíncrona(Los anotamos con @Async):


@Service
public class AsyncTask {
	
    @Async
    public void asyncWork(String s) {
    	for ( int i=0; i<20; i++ ) {
    		System.out.println("loop "+s+" "+i);
    		
    		try {
				Thread.sleep(1000);
			} catch (InterruptedException e) { e.printStackTrace(); }
    		}
    	}	

}

Ejecutar

Ahora, ya podemos utilizarlo en nuestro controlador Web(Por ejemplo):


   @Autowired
    AsyncTask asyncTask;
    
    @RequestMapping("/asyncTask")
    public String asyncTask(Model model) {
    	
	/* Estos tres métodos se ejecutarán en paralelo asíncronamente */
    	asyncTask.asyncWork("sub1");
    	asyncTask.asyncWork("sub2");
    	asyncTask.asyncWork("sub3");
    	
    	return "asyncTask";
	}

Devolver parámetros

En este ejemplo no lo hacemos, pero si quisiéramos podríamos hacer que estos métodos devolvieran un parámetro. El método debería devolver un Objeto del tipo ‘Future’ que será rellenado cuando el método finalice:

Declaración del método:


@Async
public Future<String> asyncWork() {

    System.out.println( "Ejecutando método" );

    try {
        Thread.sleep(5000);
        return new AsyncResult<String>("Que pasa neng !!!!");
    } catch (Exception e) {
        e.printStackTrace();
    	}
 
    return null;
}

Como leemos el resultado:

Future<String> future = asyncTask.asyncWork();

/* Bucle hasta que termine... */
while (true) {

        if (future.isDone()) {
            System.out.println("Por fin terminó - " + future.get());
            break;
        }

        System.out.println("Esperando un segundito mas... ");
        Thread.sleep(1000);
    }

System.out.println(“Y recuerda que también es tonto hacer algo asíncrono y después quedarte esperando hasta que termine...”);

Ya veis… Desarrollar aplicaciones modernas que hagan cosas en segundo plano es super fácil con Spring.

Leave a Reply

© Albert Coronado Calzada