Reactive Programming
Reactor . Concurrency
1
Outline
• Introduction to Reactive Programming
• What
• Why
• Reactor Nutshell
• Reactive Streams Specification
• Reactor
• Concurrency Model
2
In computing, reactive programming is a declarative
programming paradigm concerned with data streams and the
propagation of change.
https://en.wikipedia.org/wiki/Reactive_programming
3
Reactive Programming (1)
var vm = new Vue({
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
4
Reactive Programming (2)
https://docs.spring.io/spring-framework/docs/5.0.0.M4/spring-framework-reference/html/web-reactive.html
In plain terms reactive programming is about non-blocking
applications that are asynchronous and event-driven and require
a small number of threads to scale vertically (i.e. within the JVM)
rather than horizontally (i.e. through clustering).
Event loop
Event
Why
• Scales better

- C10k problem

- Efficient resource usage (vs thread per request)
• Rescue to asynchronous programming 

- Composability and readability
5
Reactor Example (1)
6
userService.getFavorites(userId)
.flatMap(favoriteService::getDetails)
.switchIfEmpty(suggestionService.getSuggestions())
.take(5)
.publishOn(UiUtils.uiThreadScheduler())
.subscribe(uiList::show, UiUtils::errorPopup);
Callback Version of (1)
7
userService.getFavorites(userId, new Callback<List<String>>() {
public void onSuccess(List<String> list) {
if (!list.isEmpty()) {
list.stream()
.limit(5)
.forEach(favId -> favoriteService.getDetails(favId,
new Callback<Favorite>() {
public void onSuccess(Favorite details) {
UiUtils.submitOnUiThread(() -> uiList.show(details));
}
public void onError(Throwable error) {
UiUtils.errorPopup(error);
}
}
));
} else {
suggestionService.getSuggestions(new Callback<List<Favorite>>() {
public void onSuccess(List<Favorite> list) {
Reactor Example (2)
8
Ids() // Flux<String>
.flatMap(id -> { // (String -> Flux<Pair<String, Integer>>) -> Flux<Pair<String, Intege
Mono<String> nameTask = Name(id);
Mono<Integer> statTask = Stat(id);
return Flux.zip(nameTask, statTask, (name, stat) -> Pair.of(name, stat));
})
.collectList() // Mono<List<Pair<String, Integer>>>
.block();
CompletableFuture Version of (2)
9
Ids().thenComposeAsync(l -> {
List<CompletableFuture<Pair>> combinationList =
l.stream().map(i -> {
CompletableFuture<String> nameTask = Name(i);
CompletableFuture<Integer> statTask = Stat(i);
return nameTask.thenCombineAsync(statTask, (name, stat) -> Pair.of(name, stat));
})
.collect(Collectors.toList());
CompletableFuture<Void> allDone = CompletableFuture.allOf(combinationList.toArray());
return allDone.thenApply(v -> combinationList.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
})
.join();
Outline
• Introduction to Reactive Programming
• What
• Why
• Reactor Nutshell
• Reactive Streams Specification
• Reactor
• Concurrency Model
10
Reactive Streams Specification
• 1.0.0 released in 2015 by Netflix, Pivotal and Lightbend and adopted in
Java 9
• Specification for Stream libraries for the JVM that
• process a potentially unbounded number of elements in sequence
• asynchronously passing elements between components with
mandatory non-blocking backpressure
11
API Components public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
public interface Subscription {
public void request(long n);
public void cancel();
}
public interface Processor<T, R> extends
Subscriber<T>, Publisher<R> {
}
• Publisher
• Subscriber
• Subscription
• Processor
12
13
Publisher
Subscriber
subscribe()
onSubscribe() onComplete()
onNext()
…
request(N)
Reactor
• Implementation of Reactive Streams specification by Pivotal
Open Source team
• Reactor abstracts publisher-subscriber and easily creates
reactive streams by Flux/Mono
• Flux/Mono provides rich operators, which wrap a publisher into
a new instance
14
userStorage.list()
.map(favoriteService::guessFavorites)
.flatMap(favoriteService::insert)
.publishOn(Schedulers.parallel())
.subscribe(favorites -> log.print(favorites));
15
Reactor
Flux<User>
Flux<Favorites>
Flux<Favorites> Mono<Favorites>
map()
• Transform the items emitted by this Flux by applying a
synchronous function to each item.
16
flatMap()
• Transform the elements emitted by this Flux asynchronously
into Publishers, then flatten these inner publishers into a single
Flux through merging, which allow them to interleave.
17
publishOn()
• Run onNext, onComplete and onError on a supplied Scheduler.
• This operator influences the threading context up to a new
occurrence of publishOn.
18
subscribe()
• Subscribe to this Flux and request unbounded demand.
• Pipeline assembly wt execution
19
Outline
• Introduction to Reactive Programming
• What
• Why
• Reactor Nutshell
• Reactive Streams Specification
• Reactor
• Concurrency Model
20
Concurrency model
• Reactor does not enforce a concurrency model
• Pipeline can be blocking/nonblocking
• Pipeline can be synchronous/asynchronous
21
Blocking
[ INFO] (Test worker) | onSubscribe([Synchronous Fuseable]
FluxRange.RangeSubscription)
[ INFO] (Test worker) | request(unbounded)
[ INFO] (Test worker) | onNext(0)
[2020-10-12T17:36:51.420][Test worker] 0
[ INFO] (Test worker) | onNext(1)
[2020-10-12T17:36:51.421][Test worker] 1
[ INFO] (Test worker) | onNext(2)
[2020-10-12T17:36:51.422][Test worker] 2
[ INFO] (Test worker) | onNext(3)
[2020-10-12T17:36:51.422][Test worker] 3
[ INFO] (Test worker) | onNext(4)
[2020-10-12T17:36:51.422][Test worker] 4
[ INFO] (Test worker) | onComplete()
[2020-10-12T17:36:51.423][Test worker] End
22
Flux.range(0, 5)
.log()
.subscribe(log::print);
log.print("End");
Nonblocking
[ INFO] (Test worker) | onSubscribe([Synchronous Fuseable]
FluxRange.RangeSubscription)
[ INFO] (Test worker) | onSubscribe([Fuseable] FluxPublishOn.PublishOnSubscriber)
[ INFO] (Test worker) | request(unbounded)
[ INFO] (Test worker) | request(256)
[ INFO] (Test worker) | onNext(0)
[ INFO] (Test worker) | onNext(1)
[ INFO] (Test worker) | onNext(2)
[ INFO] (parallel-1) | onNext(0)
[ INFO] (Test worker) | onNext(3)
[ INFO] (Test worker) | onNext(4)
[ INFO] (Test worker) | onComplete()
[2020-10-22T15:35:02.279][parallel-1] 0
[2020-10-22T15:35:02.279][Test worker] End
[ INFO] (parallel-1) | onNext(1)
[2020-10-22T15:35:02.279][parallel-1] 1
[ INFO] (parallel-1) | onNext(2)
[2020-10-22T15:35:02.280][parallel-1] 2
[ INFO] (parallel-1) | onNext(3)
[2020-10-22T15:35:02.280][parallel-1] 3
[ INFO] (parallel-1) | onNext(4)
[2020-10-22T15:35:02.280][parallel-1] 4
[ INFO] (parallel-1) | onComplete()
23
Flux.range(0, 5)
.log()
.publishOn(Schedulers.parallel())
.log()
.subscribe(log::print);
log.print("End");
Thread.sleep(5000);
Synchronous
[ INFO] (Test worker) | onSubscribe([Synchronous Fuseable]
FluxRange.RangeSubscription)
[ INFO] (Test worker) | onSubscribe([Fuseable]
FluxMapFuseable.MapFuseableSubscriber)
[ INFO] (Test worker) | request(unbounded)
[ INFO] (Test worker) | request(unbounded)
[ INFO] (Test worker) | onNext(0)
[ INFO] (Test worker) | onNext(0)
[ INFO] (Test worker) | onNext(1)
[ INFO] (Test worker) | onNext(10)
[ INFO] (Test worker) | onNext(2)
[ INFO] (Test worker) | onNext(20)
[ INFO] (Test worker) | onNext(3)
[ INFO] (Test worker) | onNext(30)
[ INFO] (Test worker) | onNext(4)
[ INFO] (Test worker) | onNext(40)
[ INFO] (Test worker) | onComplete()
[ INFO] (Test worker) | onComplete()
24
Flux.range(0, 5)
.log()
.map(i -> i * 10)
.log()
.subscribe();
log.print("End");
Asynchronous
[ INFO] (Test worker) | onSubscribe([Synchronous Fuseable]
FluxRange.RangeSubscription)
[ INFO] (Test worker) onSubscribe(FluxFlatMap.FlatMapMain)
[ INFO] (Test worker) request(unbounded)
[ INFO] (Test worker) | request(256)
[ INFO] (Test worker) | onNext(0)
[ INFO] (Test worker) | onNext(1)
[ INFO] (Test worker) | onNext(2)
[ INFO] (Test worker) | onNext(3)
[ INFO] (Test worker) | onNext(4)
[ INFO] (Test worker) | onComplete()
[2020-10-13T12:49:10.364][Test worker] End
[ INFO] (parallel-2) onNext(0)
[ INFO] (parallel-2) onNext(10)
[ INFO] (parallel-2) onNext(20)
[ INFO] (parallel-2) onNext(30)
[ INFO] (parallel-2) onNext(40)
[ INFO] (parallel-2) onComplete()
25
Flux.range(0, 5)
.log()
.flatMap(i -> Flux.just(i * 10)
.delayElements(Duration.ofMillis(1000)))
.log()
.subscribe();
log.print("End");
Thread.sleep(5000);
Bewbodfe
What you see
What you get
public void testDeadlock() {
Flux.range(0, Runtime.getRuntime().availableProcessors() * 2)
.subscribeOn(Schedulers.parallel())
.doOnNext(i -> log.print("emit " + i))
.map(i -> {
CountDownLatch latch = new CountDownLatch(1);
Mono.delay(Duration.ofMillis(100), Schedulers.parallel())
.subscribe(it -> {
latch.countDown();
});
try {
latch.await(); // kind of blocking operation
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return i;
})
.doOnNext(i -> log.print("finish " + i))
.blockLast();
}
Deadlock code snippet
Log
[2020-09-02T18:28:50.474][parallel-1] emit 0
[2020-09-02T18:28:50.610][parallel-2] unlock 0
[2020-09-02T18:28:50.611][parallel-1] finish 0
[2020-09-02T18:28:50.611][parallel-1] emit 1
[2020-09-02T18:28:50.713][parallel-3] unlock 1
[2020-09-02T18:28:50.713][parallel-1] finish 1
[2020-09-02T18:28:50.713][parallel-1] emit 2
[2020-09-02T18:28:50.815][parallel-4] unlock 2
[2020-09-02T18:28:50.816][parallel-1] finish 2
[2020-09-02T18:28:50.816][parallel-1] emit 3
[2020-09-02T18:28:50.917][parallel-5] unlock 3
[2020-09-02T18:28:50.918][parallel-1] finish 3
[2020-09-02T18:28:50.918][parallel-1] emit 4
[2020-09-02T18:28:51.022][parallel-6] unlock 4
[2020-09-02T18:28:51.023][parallel-1] finish 4
[2020-09-02T18:28:51.023][parallel-1] emit 5
[2020-09-02T18:28:51.127][parallel-7] unlock 5
[2020-09-02T18:28:51.128][parallel-1] finish 5
[2020-09-02T18:28:51.128][parallel-1] emit 6
[2020-09-02T18:28:51.232][parallel-8] unlock 6
[2020-09-02T18:28:51.232][parallel-1] finish 6
[2020-09-02T18:28:51.232][parallel-1] emit 7
[2020-09-02T18:28:51.333][parallel-9] unlock 7
[2020-09-02T18:28:51.333][parallel-1] finish 7
[2020-09-02T18:28:51.333][parallel-1] emit 8
[2020-09-02T18:28:51.435][parallel-10] unlock 8
[2020-09-02T18:28:51.436][parallel-1] finish 8
[2020-09-02T18:28:51.436][parallel-1] emit 9
[2020-09-02T18:28:51.537][parallel-11] unlock 9
[2020-09-02T18:28:51.537][parallel-1] finish 9
[2020-09-02T18:28:51.538][parallel-1] emit 10
[2020-09-02T18:28:51.640][parallel-12] unlock 10
[2020-09-02T18:28:51.641][parallel-1] finish 10
[2020-09-02T18:28:51.641][parallel-1] emit 11
Program gets stuck here
……
parallel-1 is waiting latch and latch for item 11 is to be count down by thread parallel-1
ParallelScheduler schedules tasks round robin
Guide
• Don’t do blocking(slow I/O) operation in main/ui thread, which
shall not be blocked. Use subscribeOn() and publishOn().
• A method returns mono/flux must not be blocking
• Don’t use reactive stream for computation tasks since it’s not
free to construct/execute reactive stream
Reference
• Hands-On Reactive Programming with Reactor by Rahul
Sharma
• https://projectreactor.io/docs/core/release/reference/
• https://github.com/reactive-streams/reactive-streams-jvm/
• https://spring.io/blog/2019/12/13/flight-of-the-flux-3-hopping-
threads-and-schedulers
• https://akarnokd.blogspot.com/
•
31

Reactive&amp;reactor

  • 1.
  • 2.
    Outline • Introduction toReactive Programming • What • Why • Reactor Nutshell • Reactive Streams Specification • Reactor • Concurrency Model 2
  • 3.
    In computing, reactiveprogramming is a declarative programming paradigm concerned with data streams and the propagation of change. https://en.wikipedia.org/wiki/Reactive_programming 3 Reactive Programming (1) var vm = new Vue({ watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } }
  • 4.
    4 Reactive Programming (2) https://docs.spring.io/spring-framework/docs/5.0.0.M4/spring-framework-reference/html/web-reactive.html Inplain terms reactive programming is about non-blocking applications that are asynchronous and event-driven and require a small number of threads to scale vertically (i.e. within the JVM) rather than horizontally (i.e. through clustering). Event loop Event
  • 5.
    Why • Scales better
 -C10k problem
 - Efficient resource usage (vs thread per request) • Rescue to asynchronous programming 
 - Composability and readability 5
  • 6.
  • 7.
    Callback Version of(1) 7 userService.getFavorites(userId, new Callback<List<String>>() { public void onSuccess(List<String> list) { if (!list.isEmpty()) { list.stream() .limit(5) .forEach(favId -> favoriteService.getDetails(favId, new Callback<Favorite>() { public void onSuccess(Favorite details) { UiUtils.submitOnUiThread(() -> uiList.show(details)); } public void onError(Throwable error) { UiUtils.errorPopup(error); } } )); } else { suggestionService.getSuggestions(new Callback<List<Favorite>>() { public void onSuccess(List<Favorite> list) {
  • 8.
    Reactor Example (2) 8 Ids()// Flux<String> .flatMap(id -> { // (String -> Flux<Pair<String, Integer>>) -> Flux<Pair<String, Intege Mono<String> nameTask = Name(id); Mono<Integer> statTask = Stat(id); return Flux.zip(nameTask, statTask, (name, stat) -> Pair.of(name, stat)); }) .collectList() // Mono<List<Pair<String, Integer>>> .block();
  • 9.
    CompletableFuture Version of(2) 9 Ids().thenComposeAsync(l -> { List<CompletableFuture<Pair>> combinationList = l.stream().map(i -> { CompletableFuture<String> nameTask = Name(i); CompletableFuture<Integer> statTask = Stat(i); return nameTask.thenCombineAsync(statTask, (name, stat) -> Pair.of(name, stat)); }) .collect(Collectors.toList()); CompletableFuture<Void> allDone = CompletableFuture.allOf(combinationList.toArray()); return allDone.thenApply(v -> combinationList.stream() .map(CompletableFuture::join) .collect(Collectors.toList())); }) .join();
  • 10.
    Outline • Introduction toReactive Programming • What • Why • Reactor Nutshell • Reactive Streams Specification • Reactor • Concurrency Model 10
  • 11.
    Reactive Streams Specification •1.0.0 released in 2015 by Netflix, Pivotal and Lightbend and adopted in Java 9 • Specification for Stream libraries for the JVM that • process a potentially unbounded number of elements in sequence • asynchronously passing elements between components with mandatory non-blocking backpressure 11
  • 12.
    API Components publicinterface Publisher<T> { public void subscribe(Subscriber<? super T> s); } public interface Subscriber<T> { public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); } public interface Subscription { public void request(long n); public void cancel(); } public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { } • Publisher • Subscriber • Subscription • Processor 12
  • 13.
  • 14.
    Reactor • Implementation ofReactive Streams specification by Pivotal Open Source team • Reactor abstracts publisher-subscriber and easily creates reactive streams by Flux/Mono • Flux/Mono provides rich operators, which wrap a publisher into a new instance 14
  • 15.
  • 16.
    map() • Transform theitems emitted by this Flux by applying a synchronous function to each item. 16
  • 17.
    flatMap() • Transform theelements emitted by this Flux asynchronously into Publishers, then flatten these inner publishers into a single Flux through merging, which allow them to interleave. 17
  • 18.
    publishOn() • Run onNext,onComplete and onError on a supplied Scheduler. • This operator influences the threading context up to a new occurrence of publishOn. 18
  • 19.
    subscribe() • Subscribe tothis Flux and request unbounded demand. • Pipeline assembly wt execution 19
  • 20.
    Outline • Introduction toReactive Programming • What • Why • Reactor Nutshell • Reactive Streams Specification • Reactor • Concurrency Model 20
  • 21.
    Concurrency model • Reactordoes not enforce a concurrency model • Pipeline can be blocking/nonblocking • Pipeline can be synchronous/asynchronous 21
  • 22.
    Blocking [ INFO] (Testworker) | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription) [ INFO] (Test worker) | request(unbounded) [ INFO] (Test worker) | onNext(0) [2020-10-12T17:36:51.420][Test worker] 0 [ INFO] (Test worker) | onNext(1) [2020-10-12T17:36:51.421][Test worker] 1 [ INFO] (Test worker) | onNext(2) [2020-10-12T17:36:51.422][Test worker] 2 [ INFO] (Test worker) | onNext(3) [2020-10-12T17:36:51.422][Test worker] 3 [ INFO] (Test worker) | onNext(4) [2020-10-12T17:36:51.422][Test worker] 4 [ INFO] (Test worker) | onComplete() [2020-10-12T17:36:51.423][Test worker] End 22 Flux.range(0, 5) .log() .subscribe(log::print); log.print("End");
  • 23.
    Nonblocking [ INFO] (Testworker) | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription) [ INFO] (Test worker) | onSubscribe([Fuseable] FluxPublishOn.PublishOnSubscriber) [ INFO] (Test worker) | request(unbounded) [ INFO] (Test worker) | request(256) [ INFO] (Test worker) | onNext(0) [ INFO] (Test worker) | onNext(1) [ INFO] (Test worker) | onNext(2) [ INFO] (parallel-1) | onNext(0) [ INFO] (Test worker) | onNext(3) [ INFO] (Test worker) | onNext(4) [ INFO] (Test worker) | onComplete() [2020-10-22T15:35:02.279][parallel-1] 0 [2020-10-22T15:35:02.279][Test worker] End [ INFO] (parallel-1) | onNext(1) [2020-10-22T15:35:02.279][parallel-1] 1 [ INFO] (parallel-1) | onNext(2) [2020-10-22T15:35:02.280][parallel-1] 2 [ INFO] (parallel-1) | onNext(3) [2020-10-22T15:35:02.280][parallel-1] 3 [ INFO] (parallel-1) | onNext(4) [2020-10-22T15:35:02.280][parallel-1] 4 [ INFO] (parallel-1) | onComplete() 23 Flux.range(0, 5) .log() .publishOn(Schedulers.parallel()) .log() .subscribe(log::print); log.print("End"); Thread.sleep(5000);
  • 24.
    Synchronous [ INFO] (Testworker) | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription) [ INFO] (Test worker) | onSubscribe([Fuseable] FluxMapFuseable.MapFuseableSubscriber) [ INFO] (Test worker) | request(unbounded) [ INFO] (Test worker) | request(unbounded) [ INFO] (Test worker) | onNext(0) [ INFO] (Test worker) | onNext(0) [ INFO] (Test worker) | onNext(1) [ INFO] (Test worker) | onNext(10) [ INFO] (Test worker) | onNext(2) [ INFO] (Test worker) | onNext(20) [ INFO] (Test worker) | onNext(3) [ INFO] (Test worker) | onNext(30) [ INFO] (Test worker) | onNext(4) [ INFO] (Test worker) | onNext(40) [ INFO] (Test worker) | onComplete() [ INFO] (Test worker) | onComplete() 24 Flux.range(0, 5) .log() .map(i -> i * 10) .log() .subscribe(); log.print("End");
  • 25.
    Asynchronous [ INFO] (Testworker) | onSubscribe([Synchronous Fuseable] FluxRange.RangeSubscription) [ INFO] (Test worker) onSubscribe(FluxFlatMap.FlatMapMain) [ INFO] (Test worker) request(unbounded) [ INFO] (Test worker) | request(256) [ INFO] (Test worker) | onNext(0) [ INFO] (Test worker) | onNext(1) [ INFO] (Test worker) | onNext(2) [ INFO] (Test worker) | onNext(3) [ INFO] (Test worker) | onNext(4) [ INFO] (Test worker) | onComplete() [2020-10-13T12:49:10.364][Test worker] End [ INFO] (parallel-2) onNext(0) [ INFO] (parallel-2) onNext(10) [ INFO] (parallel-2) onNext(20) [ INFO] (parallel-2) onNext(30) [ INFO] (parallel-2) onNext(40) [ INFO] (parallel-2) onComplete() 25 Flux.range(0, 5) .log() .flatMap(i -> Flux.just(i * 10) .delayElements(Duration.ofMillis(1000))) .log() .subscribe(); log.print("End"); Thread.sleep(5000);
  • 26.
  • 27.
    public void testDeadlock(){ Flux.range(0, Runtime.getRuntime().availableProcessors() * 2) .subscribeOn(Schedulers.parallel()) .doOnNext(i -> log.print("emit " + i)) .map(i -> { CountDownLatch latch = new CountDownLatch(1); Mono.delay(Duration.ofMillis(100), Schedulers.parallel()) .subscribe(it -> { latch.countDown(); }); try { latch.await(); // kind of blocking operation } catch (InterruptedException e) { throw new RuntimeException(e); } return i; }) .doOnNext(i -> log.print("finish " + i)) .blockLast(); } Deadlock code snippet
  • 28.
    Log [2020-09-02T18:28:50.474][parallel-1] emit 0 [2020-09-02T18:28:50.610][parallel-2]unlock 0 [2020-09-02T18:28:50.611][parallel-1] finish 0 [2020-09-02T18:28:50.611][parallel-1] emit 1 [2020-09-02T18:28:50.713][parallel-3] unlock 1 [2020-09-02T18:28:50.713][parallel-1] finish 1 [2020-09-02T18:28:50.713][parallel-1] emit 2 [2020-09-02T18:28:50.815][parallel-4] unlock 2 [2020-09-02T18:28:50.816][parallel-1] finish 2 [2020-09-02T18:28:50.816][parallel-1] emit 3 [2020-09-02T18:28:50.917][parallel-5] unlock 3 [2020-09-02T18:28:50.918][parallel-1] finish 3 [2020-09-02T18:28:50.918][parallel-1] emit 4 [2020-09-02T18:28:51.022][parallel-6] unlock 4 [2020-09-02T18:28:51.023][parallel-1] finish 4 [2020-09-02T18:28:51.023][parallel-1] emit 5 [2020-09-02T18:28:51.127][parallel-7] unlock 5 [2020-09-02T18:28:51.128][parallel-1] finish 5 [2020-09-02T18:28:51.128][parallel-1] emit 6 [2020-09-02T18:28:51.232][parallel-8] unlock 6 [2020-09-02T18:28:51.232][parallel-1] finish 6 [2020-09-02T18:28:51.232][parallel-1] emit 7 [2020-09-02T18:28:51.333][parallel-9] unlock 7 [2020-09-02T18:28:51.333][parallel-1] finish 7 [2020-09-02T18:28:51.333][parallel-1] emit 8 [2020-09-02T18:28:51.435][parallel-10] unlock 8 [2020-09-02T18:28:51.436][parallel-1] finish 8 [2020-09-02T18:28:51.436][parallel-1] emit 9 [2020-09-02T18:28:51.537][parallel-11] unlock 9 [2020-09-02T18:28:51.537][parallel-1] finish 9 [2020-09-02T18:28:51.538][parallel-1] emit 10 [2020-09-02T18:28:51.640][parallel-12] unlock 10 [2020-09-02T18:28:51.641][parallel-1] finish 10 [2020-09-02T18:28:51.641][parallel-1] emit 11 Program gets stuck here
  • 29.
    …… parallel-1 is waitinglatch and latch for item 11 is to be count down by thread parallel-1 ParallelScheduler schedules tasks round robin
  • 30.
    Guide • Don’t doblocking(slow I/O) operation in main/ui thread, which shall not be blocked. Use subscribeOn() and publishOn(). • A method returns mono/flux must not be blocking • Don’t use reactive stream for computation tasks since it’s not free to construct/execute reactive stream
  • 31.
    Reference • Hands-On ReactiveProgramming with Reactor by Rahul Sharma • https://projectreactor.io/docs/core/release/reference/ • https://github.com/reactive-streams/reactive-streams-jvm/ • https://spring.io/blog/2019/12/13/flight-of-the-flux-3-hopping- threads-and-schedulers • https://akarnokd.blogspot.com/ • 31