I would like to #Subscribe a method in a Runnable that is created by a ScheduledFuture, so that I can signal it from another thread whether to run. Because a ScheduledFuture creates the object at some future time, there is no scope for the #Subscribe listener to pick up my event. So, I'm wondering how long an event sits in the bus, waiting to picked up by a listener? Is the actual pub-sub synchronous wrt sending/receiving events or will they sit in a queue for some duration before timing out?
Thanks.
Guava's EventBus does not provide sticky events. Additionally, due to the design of EventBus, it's not as straightforward as it could be to extend it to implement such a sticky design, as a lot of the internals are package-private (e.g. the logic to discover which methods on a registered object are annotated with Subscribe and mapping them to the proper event type).
I do think there are some other libraries out there which do provide this, like GreenRobot's event bus (https://github.com/greenrobot/EventBus), but without introducing a new library you'll have to build it more or less from scratch.
An alternative that I've used is RxJava's Observables with a replay(1) operator, so that subscribing to the observable will always immediately invoke the subscription callback with the last item, but it's not a drop-in replacement.
Related
I have several parts of my application, that need to react to events triggered from somewhere else, so the first thing I thought about would be an event bus. These are the requirements I see:
The subscriber method should be typesafe
Implementing an interface (like Subscriber<T>) is not a problem
A subscriber should also receive any events of subtypes to the class it's registered to
Subscribers should be able to be registered with a priority (a simple int) or a default priority hardcoded somewhere in the code. When posting an event, the subscribers will be called in order. The events are mutable and some of their fields will change between subscribers
Each thread will have its own event bus and I will manually register all subscribers, so there's no need for static access
While receiving an event, it should be possible for a subscriber to unsubscribe without raising a ConcurrentModificationException
Bonus requirements I might need down the line:
Register new subscribers while handling events
Send events while receiving one. Those will be processed synchronously before proceeding with the current task
The option to "pool" events that currently have no subscriber and manually process them later (maybe by passing a Consumer).
Guava Eventbus probably does most of those things except for the priority. I can create a simple prioritized subscriber queue by using a TreeSet, but I'm not sure how to integrate it into Guava and I don't know if I want to depend on the whole library just for the bus.
Also, I might need a CopyOnWriteArrayList for the concurrent stuff (adding/removing while iterating), but I don't know about the performance implications. On that note, there probably won't be more than 10-15 subscribers at a time.
Normal events are not designed to be mutable. You should stick with immutable data. Also subscribers are not intendet to be called within a certain order or to interact with another.
For your usecase you could build different event busses for each priority. A subscriber could handover a copy of the modified event to the next priority bus.
I have old Android/java code, that contains two derives from IntentService,
and these services not run in separate processes.
The question is about the way to return result from these IntentService.
One service return result by using Handler + Runnable, to run code in main loop:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
MyApplication.get().setFoo(someThing);
}
});
the other one is uses LocalBroadcastManager.getInstance(this).sendBroadcast(in); to send message to Activity, and Activity subscribe via BroadcastReceiver on message in onResume, and unsubscribe in onPause.
Am I right, and in both case it is possible to use LiveData to simplify things?
IntentService should create LiveData and who want result should observe it,
and when new data arrives IntentService should call postValue,
or may be there are some reefs to prevent usage of LiveData here?
I think that LiveData will not help you in sending any data from Service to other components.
The problem with communication from any Service to other components is that you don't usually obtain a direct reference to the Service, therefore you can't directly "subscribe" to notifications.
Theoretically, if the Service runs in the same process, you can bind it, obtain a reference to Service object and then directly perform subscription. However, this is often an overkill and I don't see this pattern being used widely.
In your examples, there are two communication mechanisms:
Service reaches statically to Application object and sets some data. This is a communication through global state, and is generally considered an anti-pattern.
Communication through LocalBroadcastManager
From the above two mechanisms, I would use only #2 and avoid #1 at all costs.
Back to LiveData.
In order to be able to get LiveData object from the Service you will need to have a reference to that Service. This is usually impossible unless you bind Service in the same process, or use some ugly hack that involves global state.
Therefore, usefulness of LiveData in this context is very limited.
By the way, while LocalBroadcastManager is alright, I find this mechanism too complicated and restricting. Therefore, if the Service runs in the same process, I prefer to use EventBus in order to communicate from Service to other components (or vice-versa).
An example of such a communication you can see in SQLite benchmarking application that I wrote several days ago. In this app, TestService posts status changes and test results to EventBus as sticky events, and TestActivity subscribes to those events.
Both methods work with using LiveData since the purpose of LiveData is to have it on another thread and still notify users when something has changed. Seems like it would definitely replace LocalBroadcastManager.getInstance(this).sendBroadcast(in); and your IntentService would postValue. Just have your activity or anything that needs to be aware of the changes become an observer.
I have to write into a file based on the incoming requests. As multiple requests may come simultaneously, I don't want multiple threads trying to overwrite the file content together, which may lead into losing some data.
Hence, I tried collecting all the requests' data using a instance variable of PublishSubject. I subscribed publishSubject during init and this subscription will remain throughout the life-cycle of application. Also I'm observing the same instance on a separate thread (provided by Vertx event loop) which invokes the method responsible for writing the file.
private PublishSubject<FileData> publishSubject = PublishSubject.create();
private void init() {
publishSubject.observeOn(RxHelper.blockingScheduler(vertx)).subscribe(fileData -> writeData(fileData));
}
Later during request handling, I call onNext as below:
handleRequest() {
//do some task
publishSubject.onNext(fileData);
}
I understand that, when I call onNext, the data will be queued up, to be written into the file by the specific thread which was assigned by observeOn operator. However, what I'm trying to understand is
whether this thread gets blocked in WAITING state for only this
task? Or,
will it be used for other activities also when no file
writing happens?
I don't want to end up with one thread from the vertx event loop wasted in waiting state for going with this approach. Also, please suggest any better approach, if available.
Thanks in advance.
Actually RxJava will do it for you, by definition onNext() emissions will act in serial fashion:
Observables must issue notifications to observers serially (not in parallel). They may issue these notifications from different threads, but there must be a formal happens-before relationship between the notifications. (Observable Contract)
So as long as you will run blocking calls inside the onNext() at the subscriber (and will not fork work to a different thread manually) you will be fine, and no parallel writes will be happen.
Actually, you're worries should come from the opposite direction - Backpressure.
You should choose your backpressure strategy here, as if the requests will come faster then you will process them (writing to file) you might overflow the buffer and get into troubles. (consider using Flowable and choose you're backpressure strategy according to your needs.
Regarding your questions, that depends on the Scheduler, you're using RxHelper.blockingScheduler(vertx) which seems like your custom code, so I can't tell, if the scheduler is using shared thread in work queue fashion then it will not stay idle.
Anyhow, Rx will not determine this for you, the scheduler responsibility is to assign the work to some thread according to its logic.
I'm unclear on how to implement task cancellation in RXJava.
I'm interested in porting an existing API built using Guava's ListenableFuture. My use case is as follows:
I have an single operation that's composed of a sequence of futures joined by Futures.transform()
Multiple subscribers observe the operation's final future.
Each observer can cancel the final future, and all observers witness the cancellation event.
Cancellation of the final future results in the cancellation of its dependencies, e.g. in sequence 1->2->3, cancellation of 3 is propagated to 2, and so on.
There's very little info in the RxJava wiki about this; the only references I can find to cancellation mention Subscription as an equivalent to .NET's Disposable, but as far as I can see, Subscription only offers the ability to unsubscribe from subsequent values in the sequence.
I'm unclear on how to implement "any subscriber can cancel" semantics through this API. Am I thinking about this in the wrong way?
Any input would be appreciated.
It's important to learn about Cold vs Hot Observables. If your Observables are cold, then their operations will not execute if you have no subscribers. Hence to "cancel", just make sure all Observers unsubscribe from the source Observable.
However, if only one Observer of the source unsubscribes, and there are other Observers still subscribed to the source, this will not incur a "cancelling". In that case you can use (but it's not the only solution) ConnectableObservables. Also see this link about Rx.NET.
A practical way of using ConnectableObservables is to simply call .publish().refCount() on any cold Observable. What that does is create one single "proxy" Observer which relays the events from the source to the actual Observers. The proxy Observer unsubscribes when the last actual Observer unsubscribes.
To manually control a ConnectableObservable, call just coldSource.publish() and you will get an instance of ConnectableObservable. Then you can call .connect() which will return you the Subscription of the "proxy" Observer. To manually "cancel" the source, you just unsubscribe the Subscription of the proxy Observer.
For your specific problem, you can also use the .takeUntil() operator.
Suppose your "final future" is ported as finalStream in RxJava, and suppose that "cancel events" are Observables cancelStream1, cancelStream2, etc, then it becomes fairly simple to "cancel" operations resulting from finalStream:
Observable<FooBar> finalAndCancelableStream = finalStream
.takeUntil( Observable.merge(cancelStream1, cancelStream2) );
In diagrams, this is how takeUntil works, and this is how merge works.
In plain english, you can read it as "finalAndCancelableStream is the finalStream until either cancelStream1 or cancelStream2 emit an event".
I'm designing a stand-alone, multi-threaded application in Java.
I'm trying to choose the best event-handling solution for his project.
I have 1-3 threads generating events (e.g comm thread completes file upload), while other threads might want to be registered for notification on this event.
I want the event-generating and event listening to be as uncoupled as possible.
What do you suggest?
Use an event bus.
An event bus can be thought of as a
replacement for the observer pattern,
where in the observer pattern, each
component is observing an observable
directly. In the event bus pattern,
each component simply subscribes to
the event bus and waits for its event
notification methods to be invoked
when interesting events have occurred.
In this way, an event bus can be
thought of like the observer pattern
with an extra layer of decoupling.
Here's a nice presentation about using an event bus ins GWT. It should give you a good idea about the benefits (and it's quite funny, too).
EDIT
The first link is mainly given as an example. It's really not that hard implementing something similar on your own which fits your needs.
I would use ExecutorServices to manage your thread pools. This way when you have a listener to an event, you can ensure the event is added to the right service either using a Proxy, or hande coded. e.g.
public void onEventOne(final Type parameter) {
executorService.submit(new Runnable() {
public void run() {
wrappedListener.onEventOne(parameter);
}
}
}
You can pass this listener wrapper as and be sure the event will be processed using the desired thread pool.
Using a Proxy allows you to avoid this type of boiler plate code. ;)
Do you really need a solution where each thread can register as a listener for each type of event? If so, use an event bus type solution (or a centralized observable with typed events).
If you don't need this flexibility a manager-worker setup could suffice, where the manager gets notified of events (like: "I'm finished with my job") and can fire up workers as needed.
Usage of an event bus is definitely the right choise. There are various solutions out there. You can also check out MBassador https://github.com/bennidi/mbassador.
It is annotation driven, very light-weight and uses weak references (thus easy to integrate in environments where objects lifecycle management is done by a framework like spring or guice or somethign). It provides an object filtering mechanism and synchronous or asynchronous dispatch/message handling. And it's very fast!
Google Guava has an event bus as well but it uses strong references which can be a pain if you do not have full control over your object lifecycle (e.g. spring environment)
EDIT: I created a performance and feature comparison for a selection of available event bus implementations including Guava, MBassador and some more. The results are quite interesting. Check it out here
http://codeblock.engio.net/?p=37
use command design pattern to decoupling