Fundamentos de la Especificación Reactive Streams: Publisher, Subscriber y Subscription
Reactive Streams es el estándar para el procesamiento asíncrono de flujos de datos con Backpressure (contrapresión) no bloqueante. Un Publisher emite elementos, un Subscriber los consume, y la Subscription permite al consumidor solicitar exactamente cuántos elementos es capaz de procesar (request(n)).
En una línea Flux.range(1, 100).subscribe(new BaseSubscriber<Integer>() { protected void hookOnNext(Integer v) { request(1); } });
Flux.range(1, 1_000_000)
.doOnRequest(n -> System.out.println("pedidos: " + n))
.subscribe(new BaseSubscriber<Integer>() {
@Override
protected void hookOnSubscribe(Subscription s) {
request(1); // empiezo pidiendo uno
}
@Override
protected void hookOnNext(Integer valor) {
procesarDespacio(valor); // consumidor lento
if (valor < 5) request(1); // pido el siguiente solo cuando termino
else cancel(); // y puedo cancelar cuando quiera
}
});
// pedidos: 1
// pedidos: 1
// ... el productor nunca genera un millón de elementos de golpe
Cómo funciona por dentro
Reactive Streams es una especificación mínima (cuatro interfaces, incluidas en el JDK desde Java 9 como java.util.concurrent.Flow) para procesar flujos asíncronos con contrapresión. Un Publisher produce datos. Un Subscriber se suscribe y recibe una Subscription. A través de ella, el suscriptor pide cuántos elementos puede procesar con request(n), y el publicador nunca envía más de lo pedido.
La secuencia de señales es fija: onSubscribe, después cero o más onNext, y como mucho una señal final, onError u onComplete. Esa contrapresión (backpressure) es la diferencia clave con un simple callback o un stream de eventos: un consumidor lento no se ve desbordado por un productor rápido, porque es él quien marca el ritmo.
No se suele implementar estas interfaces a mano. Project Reactor, RxJava o los drivers reactivos las implementan y garantizan sus reglas; tú trabajas con operadores de alto nivel.
Se conecta con Java 9 Flow APIProject ReactorRxJava