The pits encountered in RxJava are continuously updated...

Pit encountered in RxJava

1. Unlimited creation of threads

Using .subscribeOn(Schedulers.io()) in a polling request may cause unlimited creation of threads.

Schedulers is one of the main components of RxJava. Responsible for executing Observable operations on different threads, so that time-consuming tasks can be allocated to other threads.

Here we need to understand the properties and usage of different Schedulers under Schedulers:
One of the
most common schedulers of IOScheduler . Used for IO related operations. Such as network requests and file operations. The IO scheduler is supported by the thread pool.
It first creates a worker thread, which can be reused for other operations. Of course, when this worker thread (in the case of a long task) cannot be reused, a new thread will be created to handle other operations. This benefit also brings some problems, because it allows unlimited threads to be created, so when a large number of threads are created, it will have some impact on the overall performance.

subscribeOn(Schedulers.io())

ComputationScheduler is
a computationally intensive Scheduler. Schedulers.computation() is used for computing tasks, such as event loops or callback processing, and should not be used for IO operations (please use Schedulers.io() for IO operations); the number of threads of ComputationScheduler is related to the CPU The core is closely related, because when the number of threads far exceeds the number of CPU cores, the CPU time is more wasted in the context switching of the threads. The default number of threads is equal to the number of processors

subscribeOn(Schedulers.computation())

Single
is supported by one thread. So no matter how many Observables there are, they will only run on this thread.

subscribeOn(Schedulers.single())

Immediate
This scheduler starts its task in a blocking manner in the currently active thread (rxjava2 has removed it), ignoring the currently running task. The use of RxJava2 can be ignored.

subscribeOn(Schedulers.immediate())

Trampoline
This scheduler runs on the current thread, so if you have code running on the main thread, it will add the code block to be run to the main thread's queue. It is very similar to Immediate, except that Immediate will block this thread, and Trampoline will wait for the completion of the current task. It is suitable for scenarios where there is more than one Observable and they are expected to be executed in sequence.

subscribeOn(Schedulers.trampoline())
Observable.just(1,2,3,4)
    .subscribeOn(Schedulers.trampoline())
    .subscribe(onNext);
 Observable.just( 5,6, 7,8, 9)
    .subscribeOn(Schedulers.trampoline())
    .subscribe(onNext);
 Output:
    Number = 1
    Number = 2
    Number = 3
    Number = 4
    Number = 5
    Number = 6
    Number = 7
    Number = 8
    Number = 9

Executor Scheduler() is
more like a custom IO scheduler. We can create a custom thread pool by specifying the size of the thread pool. The number of Observables suitable for use in scenarios where there are too many IO schedulers are used as follows:

Scheduler ioOne = Schedulers.from(Executors.newFixedThreadPool(5));
Scheduler fixScheduler = Schedulers.from(ioOne)
subscribeOn(fixScheduler)

Android Scheduler is
provided by the rxAndroid library, which is used to switch operations to the main thread in order to operate the ui, and is often used in the observeOn method. Use as follows:

AndroidSchedulers.mainThread()

observeOn(AndroidSchedulers.mainThread())

The reason why there is an infinite creation of threads in the case of polling requests is closely related to the implementation of IOScheduler, when the task has been executed or it is too late to release the previous thread, a new thread will be created. So the extreme situation is that the training time is too short to the previous thread has not completed the task to release, it will first create a thread, this time we should use the Executor Scheduler scheduler to customize the number of thread pools.

Scheduler ioOne = Schedulers.from(Executors.newFixedThreadPool(5));
Scheduler fixScheduler = Schedulers.from(ioOne)
2.Interval and operator are used together, an exception in the operation of the operator will interrupt the entire Interval
Observable.interval(tripInterval, TimeUnit.SECONDS)
                    .flatMap((Function<Long, ObservableSource<Response<TripResult>>>) aLong ->
                            AppDelegateImpl.getInstance()
                                    .getInfoService()
                                    .getTripInfo())
                    .subscribeOn(SchedulerPoolHelper.getInstance().getIoTrip())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new NetConsumer<TripResult>() {
                        @Override
                        public void onSuccess(TripResult result) {
                            processTripState(result);
                        }
                    }, throwable -> {
                        LogUtils.d("Trip: " + throwable.getMessage());
                    });

For example: I go back and request an interface every tripInterval seconds. We put the request interface in the flatMap operator in the middle. Once the request fails due to a request timeout or a dirty data, the entire interval will be interrupted.
This problem caused our request to fail once due to poor network, and then there is no more request.

So in this case, I nested the request in the onSuccess of the Consumer so that it would not be interrupted.

Observable.interval(tripInterval, TimeUnit.SECONDS)
                .subscribeOn(SchedulerPoolHelper.getInstance().getIoTrip())
                .subscribe(aLong -> {
                    AppDelegateImpl.getInstance().getInfoService()
                            .getTripInfo()
                            .subscribeOn(SchedulerPoolHelper.getInstance().getIoTrip())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new NetConsumer<TripResult>() {
                                @Override
                                public void onSuccess(TripResult result) {
                                    processTripState(result);
                                }
                            }, throwable -> LogUtils.d(TAG, "Trip: " + throwable.getMessage()));
                });

After consulting some materials, no good solutions were found. If the bosses have different conciseness, they can leave a message in the message area to propose different solutions.

reference

Guess you like

Origin blog.csdn.net/u011148116/article/details/106788781