You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JavaFxObservable.actionEventsOf().subscribeOn(Schedulers.newThread()) misses some emissions #77
I was learning about concurrency from your book (btw it's great) and ran into this.
When creating an Observable using JavaFxObservable factory methods and following it with subscribeOn(Scheduler) the Scheduler should be suppressed by default JavaFxScheduler.platform().
It is exectly what happens when using JavaFxObservable.actionEventsOf() but there is strange behaviour using it with JavaFxObservable.additionsOf().
It works fine (both subscribers receive their emisions) when new list element is added from inside button click handler but adding element straight from the main method causes lack of emissions to Observer[2].
Thank you, I'm glad you like it. There should never be a good reason to use subscribeOn() against any JavaFX sources. You'll always want to use observeOn() to switch elements from FX thread to different thread at that point going downstream.
It's interesting and probably not a good behavior though for folks who don't know better. I'm not quite sure what's causing the issue since there is already an internal subscribeOn().
However, I have stopped putting subscribeOn(JavaFxScheduler.platform() on other collection event factories and I must have missed this one. I wonder if getting rid of the internal subscribeOn() will fix things.
It's going to be a long one but I would really appreciate you read it.
Because currently I'm fascinated with observable collections and potential usages. I have some thoughts I would really appreciate you to consider.
I'm able to use observable collections in isolation from Fx:
Above app works perfectly fine.
In my opinion observable collections are not the part of FX UI as itself. They are widely used by FX UI but they should be able to work in separation. My thesis is - JavaFxObservale.additionsOf() (and every other Observable created from observable collections) should work with Schedulers.immediate() (and of course option to provide custom Scheduler). That would give us a chance to use Rx with collections on the Model side.
Here is my test app:
The idea behind the app is (and I'm a little bit confused it works as I expected):
list is the Model side
I get the event from Fx (number in TextField and Run button)
Immediately after getting data I switch to another thread (Executors.newSingleThreadExecutor()) and update the Model (add to list)
Other components of the View (label) are listening on model, but they should do it on the same thread (Executors.newSingleThreadExecutor()). Reason is in ListChangeListener.Change documentation
For this reason it is not safe to use this class on a different thread.
Thread switches back to FX thread and updates view (label)
The final point is - observable collections should work by default on Schedulers.immediate() and get an option of change Scheduler just like Observable.interval(period, unit, scheduler)
That was long :)
🤔 Thanks for putting this reasoning together. I do agree that JavaFX ObservableCollection should be agnostic to which thread it modifies/fires on.
However, I don't know if this is kosher to make subscribeOn() behavior do essentially what is the role of an observeOn().
You see, the ObservableList sort of acts like an event bus, or in Rx terminology it is a Subject. Subjects do not respect subscribeOn() calls but rather push emissions on whatever thread arbitrarily fires those events.
Events on ObservableList are of the same nature. One thread is going to be modifying elements and therefore also firing the listeners. A subscribeOn() is helpless and cannot control which thread modifies elements, and therefore doesn't have control over the firing events either. The Rx thing to do is to use observeOn() to take the emissions coming from that collection-modifying thread, and switch to a different thread at that point in the Observable chain rather than giving an illusion it is overriding the thread of the source.
Activity
thomasnield commentedon Nov 20, 2018
Thank you, I'm glad you like it. There should never be a good reason to use
subscribeOn()against any JavaFX sources. You'll always want to useobserveOn()to switch elements from FX thread to different thread at that point going downstream.It's interesting and probably not a good behavior though for folks who don't know better. I'm not quite sure what's causing the issue since there is already an internal
subscribeOn().https://github.com/ReactiveX/RxJavaFX/blob/2.11.x/src/main/java/io/reactivex/rxjavafx/sources/ObservableListSource.java#L63
However, I have stopped putting
subscribeOn(JavaFxScheduler.platform()on other collection event factories and I must have missed this one. I wonder if getting rid of the internalsubscribeOn()will fix things.https://github.com/ReactiveX/RxJavaFX/blob/2.11.x/src/main/java/io/reactivex/rxjavafx/sources/ObservableListSource.java#L33-L47
That is interesting regardless though.
pkrysztofiak commentedon Nov 20, 2018
It's going to be a long one but I would really appreciate you read it.
Because currently I'm fascinated with observable collections and potential usages. I have some thoughts I would really appreciate you to consider.
I'm able to use observable collections in isolation from Fx:
Above app works perfectly fine.
In my opinion observable collections are not the part of FX UI as itself. They are widely used by FX UI but they should be able to work in separation. My thesis is - JavaFxObservale.additionsOf() (and every other Observable created from observable collections) should work with Schedulers.immediate() (and of course option to provide custom Scheduler). That would give us a chance to use Rx with collections on the Model side.
Here is my test app:
The idea behind the app is (and I'm a little bit confused it works as I expected):
list is the Model side
I get the event from Fx (number in TextField and Run button)
Immediately after getting data I switch to another thread (Executors.newSingleThreadExecutor()) and update the Model (add to list)
Other components of the View (label) are listening on model, but they should do it on the same thread (Executors.newSingleThreadExecutor()). Reason is in ListChangeListener.Change documentation
(https://docs.oracle.com/javase/8/javafx/api/javafx/collections/ListChangeListener.Change.html)
The final point is - observable collections should work by default on Schedulers.immediate() and get an option of change Scheduler just like Observable.interval(period, unit, scheduler)
That was long :)
thomasnield commentedon Nov 21, 2018
🤔 Thanks for putting this reasoning together. I do agree that JavaFX ObservableCollection should be agnostic to which thread it modifies/fires on.
However, I don't know if this is kosher to make
subscribeOn()behavior do essentially what is the role of anobserveOn().You see, the
ObservableListsort of acts like an event bus, or in Rx terminology it is aSubject. Subjects do not respectsubscribeOn()calls but rather push emissions on whatever thread arbitrarily fires those events.Events on
ObservableListare of the same nature. One thread is going to be modifying elements and therefore also firing the listeners. AsubscribeOn()is helpless and cannot control which thread modifies elements, and therefore doesn't have control over the firing events either. The Rx thing to do is to useobserveOn()to take the emissions coming from that collection-modifying thread, and switch to a different thread at that point in theObservablechain rather than giving an illusion it is overriding the thread of the source.If you haven't gotten into subjects yet, my Learning RxJava book is $10 now. I've seen it go on sale for $5 on Black Fridays... which is this Friday.
https://www.packtpub.com/application-development/learning-rxjava