We use the subscribeOn and publishOn operators to switch execution contexts in the Reactor chain (Scheduler in Reactor).
In the last article, we said that Reactor's default behavior is that the same thread that executes the subscription will be used for the entire pipeline execution. What if you want to switch the thread of execution? PublishOn and SubscribeOn can be used
Let's look at a simple example:
class ReactiveJavaTutorial {
public static void main(String[] args) {
Flux<String> cities = Flux.just("New York", "London", "Paris", "Amsterdam")
.map(String::toUpperCase)
.filter(cityName -> cityName.length() <= 8)
.map(cityName -> cityName.concat(" City"))
.log();
cities.subscribe();
}
output:
17:39:41.693 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
17:39:41.712 [main] INFO reactor.Flux.MapFuseable.1 - | onSubscribe([Fuseable] FluxMapFuseable.MapFuseableSubscriber)
17:39:41.714 [main] INFO reactor.Flux.MapFuseable.1 - | request(unbounded)
17:39:41.715 [main] INFO reactor.Flux.MapFuseable.1 - | onNext(NEW YORK City)
17:39:41.715 [main] INFO reactor.Flux.MapFuseable.1 - | onNext(LONDON City)
17:39:41.715 [main] INFO reactor.Flux.MapFuseable.1 - | onNext(PARIS City)
17:39:41.716 [main] INFO reactor.Flux.MapFuseable.1 - | onComplete()
The name of the thread in square brackets, in this case, is main . You can see that the main thread is used throughout the pipeline executor.
Sometimes, we might want to tell Reactor not to use the same thread for the entire pipeline. I can use the subscribeOn() and publishOn() methods to effect.
subscribeOn() method
subscribeOn()
method works for subscription process. We can put it anywhere in the response chain . It receives a Scheduler parameter and selects threads to execute in the provided thread pool.
In the example below, we use a bounded elastic thread pool (Schedulers.boundElastic())
.
@Test
public void testSubscribeThread() {
Flux<String> cities = Flux.just("New York", "London", "Paris", "Amsterdam")
.subscribeOn(Schedulers.boundedElastic())
.map(String::toUpperCase)
.filter(cityName -> cityName.length() <= 8)
.map(cityName -> cityName.concat(" City"))
.map(TestCase::concat)
.map(TestCase::stringToUpperCase)
.log();
// cities.subscribe();
System.out.println(cities.blockFirst());
}
PS: The case provided in the original text has no output and is simply modified.
output:
20:07:53.517 [main] DEBUG reactor.util.Loggers - Using Slf4j logging framework
20:07:53.558 [main] INFO reactor.Flux.Map.1 - onSubscribe(FluxMap.MapSubscriber)
20:07:53.560 [main] INFO reactor.Flux.Map.1 - request(unbounded)
concat: boundedElastic-1
stringToUpperCase: boundedElastic-1
20:07:53.564 [boundedElastic-1] INFO reactor.Flux.Map.1 - onNext(NEW YORK CITY CITY)
20:07:53.565 [boundedElastic-1] INFO reactor.Flux.Map.1 - cancel()
NEW YORK CITY CITY
It can be seen that the main
thread started to subscribe, but was switched to boundedElastic-1
thread. We provide a Scheduler (Schedulers.boundedElastic())
and then a thread from this thread pool is selected to replace the main
thread.
publishOn() method
publishOn()
method is very similar to subscribeOn()
, but with one major difference.
Let's see an example:
class ReactiveJavaTutorial {
public static void main(String[] args) {
Flux.just("New York", "London", "Paris", "Amsterdam")
.map(ReactiveJavaTutorial::stringToUpperCase)
.publishOn(Schedulers.boundedElastic())
.map(ReactiveJavaTutorial::concat)
.subscribe();
}
private static String stringToUpperCase(String name) {
System.out.println("stringToUpperCase: " + Thread.currentThread().getName());
return name.toUpperCase();
}
private static String concat(String name) {
System.out.println("concat: " + Thread.currentThread().getName());
return name.concat(" City");
}
}
Here, we put one publishOn()
in two map operations. Let's look at the output:
stringToUpperCase: main
stringToUpperCase: main
stringToUpperCase: main
concat: boundedElastic-1
concat: boundedElastic-1
concat: boundedElastic-1
It can be seen that all operations before publishOn
are executed by the main thread, and all operations after publishOn
are executed by boundedElastic-1. This is because publishOn
acts as any other operator. It receives the signal from upstream and replays it downstream when a callback is executed on the associated Scheduler
to a worker
.
This is the main difference between publishOn
and subscribeOn()
. Wherever we put subscribeOn()
, what it provides Scheduler
will apply to the entire response chain.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。