Para los que no lo sepan: Rx es monohilo por defecto.
Un entorno multihilo rompe un stream secuencial inmutable; puesto que deja de ser secuencial.
Aun así, todavía hay posibilidad (y potencial) de ejecutar procesos en paralelo.
Empecemos por un sencillo ejemplo en el que nos subscribimos a una lista de enteros:
public static int DoHeavyThings(int i) { Thread.sleep(5000); return i; }
Observable<Integer> nums = Observable.range(1,10); nums.map(n -> DoHeavyThings(n)) .subscribe(res -> System.out.println(res + " --> " + Thread.currentThread().getName()));
Esto se ejecuta en el hilo principal y bloqueamos la UI... Probemos a suscribirnos a otro/s hilo/s usando un scheduler para computación cuya implementación escala según los núcleos de nuestra computadora.
nums.subscribeOn(Schedulers.computation()) .map(n -> DoHeavyThings(n)) .subscribe(res -> System.out.println(res + " --> " + Thread.currentThread().getName()));
Pues tampoco... Usa otro hilo y no bloquea la UI pero sólo usa un hilo y sigue procesando lo elementos de forma secuencial.
¿Cómo puedo hacer esto sin escapar de la mónada?
La respuesta es crear un stream inmutable por cada elemento y suscribir cada uno al scheduler:
nums.flatMap(n -> Observable.just(n) .subscribeOn(Schedulers.computation()) .map(o -> intenseCalculation(o)) ) .subscribe(res -> System.out.println(res + " --> " + Thread.currentThread().getName()));
Hemos fastidiado el orden de la secuencia pero tenemos cálculos en paralelo.
Yo a esto le veo potencial. Imaginaos que no disponemos de GPU y debemos procesar los pixeles de una imagen para algún efecto visual. Se podría dividir la imagen en secciones, dejar que cada hilo procese una sección y después volver a montar la imagen procesada con los items del stream final que pueden incluir, a parte de la sección de la imagen, metainformación suficiente para remontar la imagen.
Si el procesado de las secciones de la imagen requiere consultas a pixeles vecinos para los calculos siempre se puede precalcular las derivadas parciales de los pixeles que bordean la sección y pasarlas también como metainformación de esa secciónn de la imagen.
Y como todo está implementado con Rx podemos ir mostrando en la UI las secciones procesadas en cuanto vayan llegando, produciendo un efecto de peli de hackers bien molón e increiblemente fácil de implementar. :-D
Happy coding bastardillos!
No hay comentarios:
Publicar un comentario