Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive Mesh

Reactive Mesh

@DevFest Belgium 2016.
Overview on some of the reactive frameworks for Android and Java (RxJava 1.x/2.x, Reactor, Akka, Agera). Examples, comparison and interoperability.

Kalin Maldzhanski

October 23, 2016
Tweet

Other Decks in Programming

Transcript

  1. Why we like FRP • Nice, readable and declarative •

    No callback hell, no AsyncTask • finally easy and clean async computations on Java (it would be lovely to have those by default in JDK 9, it is anyway late :)
  2. …a wish… • Responsive • Elastic • Resilient • Message

    Driven Responsive: The system responds in a timely manner if at all possible. Responsiveness is the cornerstone of usability and utility, but more than that, responsiveness means that problems may be detected quickly and dealt with effectively. Responsive systems focus on providing rapid and consistent response times, establishing reliable upper bounds so they deliver a consistent quality of service. This consistent behaviour in turn simplifies error handling, builds end user confidence, and encourages further interaction. Resilient: The system stays responsive in the face of failure. This applies not only to highly-available, mission critical systems — any system that is not resilient will be unresponsive after a failure. Resilience is achieved by replication, containment, isolation and delegation. Failures are contained within each component, isolating components from each other and thereby ensuring that parts of the system can fail and recover without compromising the system as a whole. Recovery of each component is delegated to another (external) component and high-availability is ensured by replication where necessary. The client of a component is not burdened with handling its failures. Elastic: The system stays responsive under varying workload. Reactive Systems can react to changes in the input rate by increasing or decreasing the resources allocated to service these inputs. This implies designs that have no contention points or central bottlenecks, resulting in the ability to shard or replicate components and distribute inputs among them. Reactive Systems support predictive, as well as Reactive, scaling algorithms by providing relevant live performance measures. They achieve elasticity in a cost- effective way on commodity hardware and software platforms. Message Driven: Reactive Systems rely on asynchronous message-passing to establish a boundary between components that ensures loose coupling, isolation and location transparency. This boundary also provides the means to delegate failures as messages. Employing explicit message-passing enables load
  3. … a problem to solve… • Painless communication across async

    boundaries • Non blocking -> Push Model -> Cool | OOM • Backpressure • Interoperability, Contracts, Rules
  4. Players • RxJava 1.x • Agera • RxJava 2.x •

    Reactor Core • Akka Stream • Reactive Streams
  5. Agera • Observable • Updatable • Supplier • Repository (Observable,

    Supplier) • UpdateDispatcher (Observable, Updatable)
  6. RxJava 2.x • Observable / Flowable • Observer / Subscriber

    • Disposable / Subscription • Subject / FlowableProcessor
  7. Reactive Streams public interface Publisher<T> { void subscribe(Subscriber<? super T>

    s); } public interface Subscriber<T> { void onSubscribe(Subscription s); void onNext(T t); void onError(Throwable t); void onComplete(); } public interface Subscription { void request(long n); void cancel(); } public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { }
  8. Reactive Streams vs RxJava 1.x public interface Publisher<T> { void

    subscribe(Subscriber<? super T> s); } public interface Subscriber<T> { void onSubscribe(Subscription s); void onNext(T t); void onError(Throwable t); void onComplete(); } public interface Subscription { void request(long n); void cancel(); } public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { } public class Observable<T> { Subscription subscribe(Subscriber<? super T> s); } public interface Subscriber<T> { void onNext(T t); void onError(Throwable t); void onCompleted(); } public interface Subscription { boolean isUnsubscribed(); void unsubscribe(); } public abstract class Subject<T, R> extends Observable<R> implements Observer<T> { }
  9. RxJava 2.x vs RxJava 1.x public interface Flowable<T> { void

    subscribe(Subscriber<? super T> s); } public interface Subscriber<T> { void onSubscribe(Subscription s); void onNext(T t); void onError(Throwable t); void onComplete(); } public interface Subscription { void request(long n); void cancel(); } public interface FlowableProcessor<T, R> extends Subscriber<T>, Flowable<R> { } public class Observable<T> { Subscription subscribe(Subscriber<? super T> s); } public interface Subscriber<T> { void onNext(T t); void onError(Throwable t); void onCompleted(); } public interface Subscription { boolean isUnsubscribed(); void unsubscribe(); } public abstract class Subject<T, R> extends Observable<R> implements Observer<T> { } more in here: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0
  10. Reactive Streams vs Agera public interface Publisher<T> { void subscribe(Subscriber<?

    super T> s); } public interface Subscriber<T> { void onSubscribe(Subscription s); void onNext(T t); void onError(Throwable t); void onComplete(); } public interface Subscription { void request(long n); void cancel(); } public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { } public interface Observable { void addUpdatable(@NonNull Updatable updatable); void removeUpdatable(@NonNull Updatable updatable) } public interface Updatable { void update(); } public interface Supplier<T> { T get(); } public interface Repository<T> extends Observable, Supplier<T> {} public interface UpdateDispatcher extends Observable, Updatable {}
  11. Interoperability RxJava 2.x Reactor Core Akka Stream Reactive Streams RxJava

    1.x Agera RxJavaReactiveStreams RxJava2Interop RxAgera
  12. Interoperability public abstract class RxReactiveStreams { public static <T> Publisher<T>

    toPublisher(Observable<T> observable) public static <T> Observable<T> toObservable(final Publisher<T> publisher) public static <T> org.reactivestreams.Subscriber<T> toSubscriber(final rx.Subscriber<T> rxSubscriber) public static <T> Publisher<T> toPublisher(Completable completable) public static Completable toCompletable(Publisher<?> publisher) public static <T> Publisher<T> toPublisher(Single<T> single) public static <T> Single<T> toSingle(Publisher<T> publisher) } Reactive Streams RxJava 1.x https://github.com/ReactiveX/RxJavaReactiveStreams
  13. Interoperability public final class RxJavaInterop { public static <T> io.reactivex.Flowable<T>

    toV2Flowable(rx.Observable<T> source) public static <T> io.reactivex.Observable<T> toV2Observable(rx.Observable<T> source) public static <T> io.reactivex.Maybe<T> toV2Maybe(rx.Completable source) public static <T> io.reactivex.Maybe<T> toV2Maybe(rx.Single<T> source) public static <T> io.reactivex.Single<T> toV2Single(rx.Single<T> source) public static io.reactivex.Completable toV2Completable(rx.Completable source) public static <T> rx.Observable<T> toV1Observable(org.reactivestreams.Publisher<T> source) public static <T> rx.Observable<T> toV1Observable(io.reactivex.ObservableSource<T> source, io.reactivex.BackpressureStrategy strategy) public static <T> rx.Single<T> toV1Single(io.reactivex.SingleSource<T> source) public static rx.Completable toV1Completable(io.reactivex.CompletableSource source) public static <T> rx.Single<T> toV1Single(io.reactivex.MaybeSource<T> source) public static <T> rx.Completable toV1Completable(io.reactivex.MaybeSource<T> source) } RxJava 2.x RxJava 1.x https://github.com/akarnokd/RxJava2Interop
  14. Interoperability public final class RxAgeraConverter { public static rx.Observable<Object> toRxObservable(@NonNull

    Observable ageraObservable) public static Observable toAgeraObservable(@NonNull rx.Observable<?> rxObservable) public static UpdateDispatcher toAgeraUpdateDispatcher(@NonNull Subject<Object, ?> rxSubject) public static Subject<Object, Object> toRxSubject(@NonNull UpdateDispatcher ageraUpdateDispatcher) } Agera RxJava 1.x https://github.com/akarnokd/RxAgera
  15. Akka Composition RunnableGraph.fromGraph( GraphDSL.create(builder -> { final SourceShape<Integer> A =

    builder.add(Source.single(0)); final UniformFanOutShape<Integer, Integer> B = builder.add(Broadcast.create(2)); final UniformFanInShape<Integer, Integer> C = builder.add(Merge.create(2)); final FlowShape<Integer, Integer> D = builder.add(Flow.of(Integer.class).map(i -> i + 1)); final UniformFanOutShape<Integer, Integer> E = builder.add(Balance.create(2)); final UniformFanInShape<Integer, Integer> F = builder.add(Merge.create(2)); final SinkShape<Integer> G = builder.add(Sink.foreach(System.out::println)); builder.from(F.out()).toInlet(C.in(0)); builder.from(A).toInlet(B.in()); builder.from(B.out(0)).toInlet(C.in(1)); builder.from(C.out()).toInlet(F.in(0)); builder.from(B.out(1)).via(D).toInlet(E.in()); builder.from(E.out(0)).toInlet(F.in(1)); builder.from(E.out(1)).to(G); return ClosedShape.getInstance(); }));
  16. Simple Flow • RxJava 1.x Observable.range(1, 100).map(i -> i +

    33) .subscribe(System.out::println); • RxJava 2.x Flowable.range(1, 100).map(i -> i + 33) .subscribe(System.out::println); • Reactor Core Flux.range(1, 100).map(i -> i + 33) .subscribe(System.out::println); • Akka Stream Source.range(1, 100).map(i -> i + 33) .runForeach(System.out::println, materializer);
  17. Create Source RxJava 1.x Observable.just(8); Observable.from(new Integer[]{8}); Observable.fromCallable(...); Observable.fromEmitter(...); Observable.empty();

    Observable.never(); Observable.error(new IllegalStateException("why 8")); Observable.create(subscriber -> { subscriber.onNext(8); subscriber.onCompleted(); }); Observable.just(8);
  18. Create Source RxJava 2.x Observable.just(8); Observable.fromArray(new Integer[]{8}); Observable.fromCallable(...); Observable.fromFuture(...); Observable.fromIterable(...);

    Observable.fromPublisher(...); Observable.empty(); Observable.never(); Observable.error( new IllegalStateException("why 8")); Observable.create(e -> { e.setCancellable(() -> cleanMe()); e.onNext(8); e.onComplete(); }); Flowable.just(8); Flowable.fromArray(new Integer[]{8}); Flowable.fromCallable(...); Flowable.fromFuture(...); Flowable.fromIterable(...); Flowable.fromPublisher(...); Flowable.empty(); Flowable.never(); Flowable.error( new IllegalStateException("why 8")); Flowable.create(e -> { e.setCancellable(() -> cleanMe()); e.onNext(8); e.onComplete(); }, FlowableEmitter.BackpressureMode.BUFFER);
  19. Create Source Reactor Flux.just(8); Flux.fromArray(new Integer[]{8}); Flux.from(publisher); Flux.fromIterable(...); Flux.fromStream() Flux.empty();

    Flux.never(); Flux.error(new IllegalStateException("why 8")); Flux.create(e -> { e.setCancellation(() -> cleanMe()); e.next(8); e.complete(); }, FluxSink.OverflowStrategy.BUFFER);
  20. Backpressure • RxJava 1.x - knows, not all respect it

    • RxJava 2.x Observables - doesn’t know • RxJava 2.x Flowables - knows • Reactor Core - knows • Akka Stream - knows https://github.com/ReactiveX/RxJava/wiki/Backpressure
  21. Fusion Why? • many sequences are started from constant or

    quasi-constant sources such as just(), from(T[]), from(Iterable), fromCallable() which don't really need the thread-safety dance in a sequence of operators, • some pairs of operators can share internal components such as Queues and • some operators can tell if they consumed the value or dropped it, avoiding request(1) call overhead. http://akarnokd.blogspot.be/2016/03/operator-fusion-part-1.html
  22. Macro Fusion • Replacing an operator with another operator •

    Replacing an operator with a custom operator • Replacing during subscription-time • Replacing with the same operator but with modified parameters
  23. Reactive-Streams-Commons Fusion Matrix First \ Second CombineLatest - inner ConcatMap

    Distinct DistinctFuseable DistinctUntilChanged Filter FilterFuseable FlatMap FlatMap - inner FlattenIterable Map MapFuseable Merge - inner ObserveOn Peek PeekFuseable Publish SkipWhile SubscribeOn Take TakeFuseable Using - inner Zip - inner Aggregate Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async All Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Any Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Array Unfuseable Sync Sync Conditional Sync Conditional Conditional Sync Conditional Sync Conditional Unfuseable Sync Sync Sync Conditional Sync Conditional Sync Sync Conditional Sync Conditional Sync Conditional Unfuseable Sync Conditional Sync Conditional Sync Conditional Sync AsyncProcessor Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Callable Scalar Async Async Async Unfuseable Async Async Scalar Scalar Async Scalar Async Async Async Scalar Async Scalar Async Unfuseable Async Async Unfuseable Scalar Async Async Async Scalar Async CallableSubscribeOn Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Unfuseable Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Collect Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async CombineLatest Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async CompletableFuture Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Count Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Distinct Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Sync Async Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async DistinctFuseable Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Sync Async Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async DistinctUntilChanged Unfuseable Unfuseable Conditional Conditional Conditional Conditional Conditional Unfuseable Unfuseable Unfuseable Conditional Conditional Unfuseable Unfuseable Conditional Conditional Unfuseable Conditional Unfuseable Conditional Conditional Conditional Unfuseable ElementAt Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Empty Scalar Unfuseable Unfuseable Unfuseable Unfuseable Unfuseable Unfuseable Scalar Scalar Scalar Unfuseable Unfuseable Scalar Scalar Unfuseable Unfuseable Unfuseable Unfuseable Scalar Unfuseable Unfuseable Unfuseable Scalar Filter Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Unfuseable Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async FilterFuseable Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Unfuseable Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async FlattenIterable Unfuseable Sync Sync Sync Unfuseable Sync Sync Unfuseable Sync Sync Sync Sync Sync Sync Unfuseable Sync Sync Unfuseable Unfuseable Sync Sync Sync Sync Future Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Generate Unfuseable Sync Sync Sync Unfuseable Sync Sync Unfuseable Sync Sync Sync Sync Sync Unfuseable Unfuseable Sync Sync Unfuseable Unfuseable Sync Sync Sync Sync GroupBy Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async GroupBy - inner Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async HasElements Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Iterable Unfuseable Sync Sync Conditional Sync Conditional Conditional Sync Conditional Sync Conditional Unfuseable Sync Sync Sync Conditional Sync Conditional Sync Sync Conditional Sync Conditional Sync Conditional Unfuseable Sync Conditional Sync Conditional Sync Conditional Sync Just Scalar Sync Sync Sync Unfuseable Sync Sync Scalar Scalar Sync Scalar Sync Sync Sync Scalar Sync Scalar Sync Unfuseable Sync Sync Unfuseable Scalar Sync Sync Sync Scalar Sync Map Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Unfuseable Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async MapFuseable Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Unfuseable Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async ObserveOn Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Peek Unfuseable Unfuseable Conditional Conditional Conditional Conditional Conditional Unfuseable Unfuseable Unfuseable Conditional Conditional Unfuseable Unfuseable Conditional Conditional Unfuseable Conditional Unfuseable Conditional Conditional Conditional Unfuseable PeekFuseable Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Sync Async Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async Publish Unfuseable Sync Async Sync Async Sync Async Unfuseable Sync Async Sync Async Unfuseable Sync Async Sync Async Sync Async Sync Async Sync Async Sync Async Unfuseable Sync Async Sync Async Unfuseable Unfuseable Sync Async Sync Async Sync Async Sync Async Range Unfuseable Sync Sync Conditional Sync Conditional Conditional Sync Conditional Sync Conditional Unfuseable Sync Sync Sync Conditional Sync Conditional Sync Sync Conditional Sync Conditional Sync Conditional Unfuseable Sync Conditional Sync Conditional Sync Conditional Sync Reduce Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async ReplayProcessor Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Single Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async SkipWhile Unfuseable Unfuseable Conditional Conditional Conditional Conditional Conditional Unfuseable Unfuseable Unfuseable Conditional Conditional Unfuseable Unfuseable Conditional Conditional Unfuseable Conditional Unfuseable Conditional Conditional Conditional Unfuseable Stream Unfuseable Sync Sync Conditional Sync Conditional Conditional Sync Conditional Sync Conditional Unfuseable Sync Sync Sync Conditional Sync Conditional Sync Sync Conditional Sync Conditional Sync Conditional Unfuseable Sync Conditional Sync Conditional Sync Conditional Sync StreamCollector Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async SubscribeOn Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async SubscribeOnValue Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Take Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Sync Async Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async TakeFuseable Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Sync Async Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async TakeLast Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async TakeLastOne Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async UnicastProcessor Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Using Unfuseable Sync Async Sync Async Conditional Sync Async Conditional Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Sync Async Sync Async Conditional Sync Async Conditional Sync Async Sync Async Conditional Sync Async Conditional Sync Async Conditional Unfuseable Sync Async Conditional Sync Async Conditional Sync Async Conditional Sync Async Window - inner Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async WindowBatch - inner Unfuseable Async Async Async Unfuseable Async Async Unfuseable Async Async Async Async Async Async Unfuseable Async Async Unfuseable Unfuseable Async Async Async Async Reactive-Streams-Commons Fusion Matrix https://rawgit.com/reactor/reactive-streams-commons/master/f... https://rawgit.com/reactor/reactive-streams-commons/master/fusion-matrix.html
  24. The beginning https://channel9.msdn.com/Shows/Going+Deep/Expert-to-Expert-Brian-Beckman-and-Erik-Meijer-Inside-the-NET-Reactive-Framework-Rx RxJava https://github.com/ReactiveX/RxJava Agera https://github.com/google/agera Reactor Core https://github.com/reactor/reactor-core

    Akka Stream https://github.com/akka/akka/tree/master/akka-stream Reactive Streams Specification for the JVM http://www.reactive-streams.org/ https://github.com/reactive-streams/reactive-streams-jvm Official modules for the Reactor project https://github.com/reactor/reactor-addons Utilities for use with rxjava https://github.com/davidmoten/rxjava-extras A joint research effort for building highly optimized Reactive-Streams compliant operators. https://github.com/reactor/reactive-streams-commons Adapter between RxJava and ReactiveStreams https://github.com/ReactiveX/RxJavaReactiveStreams Library to convert between RxJava 1.x and 2.x reactive types. https://github.com/akarnokd/RxJava2Interop Extra sources, operators and components and ports of many 1.x companion libraries for RxJava 2.x. https://github.com/akarnokd/RxJava2Extensions Convert between RxJava and Agera reactive base types https://github.com/akarnokd/RxAgera