Multithreaded Observer in Java - preserve proper order - java

I am implementing something that I would call "Observable Set". It is just a normal set, but it can have some observers that are notified about adding new elements.
What is important for me, is that elements may be added from many threads at time, and also there are many observing threads. I hold Observers in CopyOnWriteArrayList (it is thread-safe). The key point is to inform observers about adding elements in way, that informing order for each of observers is the same as order of adding elements.
What is best approach?
The most naive one is to put adding and informing in "synchronized" block. But i believe it can be slow etc.
Second I've tried was to just add element to set, and add it to "informing queue". With each addition of element it was checked whether informing is turned on. If not, it was started until the queue was empty. It was working quite OK but i was afraid that it wasn't nice approach.
The last that I've implemented, i would call as "informing threads". With adding observers, each observer has it's own "informing thread" created. That thread runs in background and checks if it's at end of global "informing queue". If it isn't it informs specific thread about new elements. However I've problems with synchronization, and while(true) loop. I don't know how to set condition to end thread. The next problem I noticed when writing it, is that every new thread will be informed from beginning... It's not good.
I hope I have described everything quite well. If not, please let me know, i will try to fix it.
What is best way to accomplish this task?
Thanks!

Your second solution could be improved to use a BlockingQueue: with it you don't need to check whether "informing is turned on", you just call take(), and it will wait for something to appear in the queue.
You could also look into the RxJava project. It is somewhat complex, but it has lots of features you might need.
It extends the observer pattern to support sequences of data/events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety and concurrent data structures.

Related

Conccurent Modification and Synchronization of arraylists [duplicate]

This question already has answers here:
How do I make my ArrayList Thread-Safe? Another approach to problem in Java?
(8 answers)
Closed 7 years ago.
This question is more about asking if my way of doing something is the "correct" way or not. I have some program that involves constantly updating graphical components. To that effect, I have the method below.
public void update(){
for (BaseGameEntity movingEntity : movingEntityList) {
((MovingEntity)movingEntity).update();
}
}
Essentially, the class containing this method has a list of all graphical objects that need updating and it loops through, calling their respective update methods.
The issue comes when I have to add new entities or remove current entities from this list. The addition and removal of entities is handled by a different thread, and as you can guess, this results in a Concurrent Modification Exception if I try to add/remove entities while also looping through and updating their graphical components.
My ad hoc solution was to simply throw a try-catch block around this and just ignore any concurrent modification exceptions that crop up - in effect, not updating at that specific time. This does exactly what I want and no problems occur.
public void update(){
try{
for (BaseGameEntity movingEntity : movingEntityList) {
((MovingEntity)movingEntity).update();
}
}catch(ConcurrentModificationException e){
//Do Nothing
}
}
However, my question is, is this a "proper" way of handling this issue? Should I perhaps be doing something akin to what is outlined in this answer? What is the "correct" way to handle this issue, if mine is wrong? I'm not looking specifically for ways to make my arraylist thread safe such as through synchronized lists, I'm specifically asking if my method is a valid method or if there is some reason I should avoid it and actually use a synchronized list.
The proper way would be to synchronize the list with Collections.synchronizedList():
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
If you are traversing way more than the number of times you update your list, you can also use CopyOnWriteArrayList.
If you don't mind occasional missing updates (or if they happen way too infrequently for the price of synchronization), your way is fine.
Is this a "proper" way of handling this issue?
If you do not mind getting an increase of concurrency at the expense of dropping the updates on error, then the answer is "yes". You do run the risk of not completing an update multiple times in a row, when significant additions and removals to the list happen often.
On the other hand, when the frequency of updates is significantly higher than the frequency of adding/removing an object, this solution sounds reasonable.
Should I perhaps be [using synchronized]?
This is also a viable solution. The difference is that an update would no longer be able to proceed when an update is in progress. This may not be desirable when the timing of calls to update is critical (yet it is not critical to update everything on every single call).
Some people consider it as a duplicate of all the generic synchronization questions. I think this is not the case. You are asking for a very specific constellation, and whether your solution is "OK", in this sense.
Based on what you described, the actual goal seems to be clear: You want to quickly and concurrently iterate over the entities to call the update method, and avoid any synchronization overhead that may be implied by using Collections#synchronizedList or similar approaches.
Additionally, I assume that the main idea behind the solution that you proposed was that the update calls have to be done very often and as fast as possible, whereas adding or removing entities happens "rarely".
So, adding and removing elements is an exception, compared to the regular operations ;-)
And (as dasblinkenlight already pointed out in his answer) for such a setup, the solution of catching and ignoring the ConcurrentModificationException is reasonable, but you should be aware of the consequences.
It might happen that the update method of some entities is called, and then the loop bails out due to the ConcurrentModificationException. You should be absolutely sure that this does not have undesirable side-effects. Depending on what update actually does, this might, for example, cause some entities to move faster over the screen, and others to not move at all, because their update calls had been missed due to several ConcurrentModificationExceptions. This may be particularly problematic if adding and removing entities is not an operation that happens rarely: If one thread constantly adds or removes elements, then the last elements of the list may never receive an update call at all.
If you want some "justification by example": I first encountered this pattern in the JUNG Graph Library, for example, in the SpringLayout class and others. When I first saw it, I cringed a little, because at the first glance it looks horribly hacky and dangerous. But here, the justification is the same: The process has to be as fast as possible, and modifications to the graph structure (which would cause the exception) are rare. Note that the JUNG guys actually do recursive calls to the respective method when the ConcurrentModificationException happens - simply because they can't always assume the method to be called constantly by another thread. This, in turn, can have nasty side-effects: If another thread does constant modifications, and the ConcurrentModificationException is thrown each time when the method is called, then this will end with a StackOverflowError... But this is not the case for you, fortunately.

Reorder queue in Java's ThreadPoolExecutor [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java Executors: how can I set task priority?
I have a ThreadPoolExecutor built using a LinkedBlockingDequeue and I want to manipulate the underlying queue, however reading this in the documentation makes me very nervous.
Queue maintenance
Method getQueue() allows access to the work queue for purposes of monitoring and debugging. Use of this method for any other purpose is strongly discouraged. Two supplied methods, remove(java.lang.Runnable) and purge() are available to assist in storage reclamation when large numbers of queued tasks become cancelled.
Specifically I want to be able to
Check the queue to see if an element already exists. I assume this is fine as no locking should be necessary to just view the elements in the queue.
I want to reorder the queue based on some signal. This can obviously be troublesome. I was wondering if there is a preferred way to do this so that I won't mess up the queue for other uses.
Thanks
getQueue() will always return the exact BlockingQueue<Runnable> that you pass into the ThreadPoolExecutor.
The worry with the documentation is that you could easily run into issues with double-running if you cannot guarantee the thread safety of the BlockingQueue. If you use a PriorityBlockingQueue, and only use remove and add (or, more directly, offer), then you will be safe, and you can even do it directly from the getQueue().
In other words, whenever your signal tells you that some Runnable's priority has changed, then you should remove it and check the result of the remove (true if removed), and only if it was actually removed, then you should re-add it. You are not guaranteed that something won't be picked up inbetween those operations, but you are at least guaranteed that you will not double-run the Runnable, which could easily happen if done with contains -> remove -> add.
Either that, or you can write your own implementation of a BlockingQueue that uses a Comparator (like the PriorityBlockingQueue) that finds the highest priority whenever asked for new data. This sounds like a lot more work given the various interfaces involved.

java single writer and multiple reader

Sorry if this was asked before, but I could not find my exact scenario.
Currently I have a background thread that adds an element to a list and removes the old data every few minutes. Theoretically there can be at most 2 items in the list at a time and the items are immutable. I also have multiple threads that will grab the first element in the list whenever they need it. In this scenario, is it necessary to explicitly serialized operations on the list? My assumption that since I am just grabbing references to the elements, if the background thread deletes elements from the list, that should not matter since the thread already grabs a copy of the reference before the deletion. There is probably a better way to do this. Thanks in advanced.
Yes, synchronization is still needed here, because adding and removing are not atomic operations. If one thread calls add(0, new Object()) at the same time another calls remove(0), the result is undefined; for example, the remove() might end up having no effect.
Depending on your usage, you might be able to use a non-blocking list class like ConcurrentLinkedQueue. However, given that you are pushing one change every few minutes, I doubt you are gaining much in performance by avoiding synchronization.

Explanation for different behavior in Vector.set() and ArrayList.set()

Project background aside, I've implemented a table of custom JComboBoxes. Each row of ComboBoxes is exclusive: while each ComboBox has its own model (to allow different selections), each choice can only be selected once per row. This is done by adding a tag to the front of an item when selected and removing it again when deselected. If a user tries to select a tagged item, nothing happens.
However, this only works when using a Vector as the backing for the list of options. I can get the Vector of strings, use either set() or setElementAt(), and boom presto it works.
With an ArrayList instead of a Vector, however, this doesn't work at all. I was under the impression that ArrayLists functioned similarly in that I can retrieve an anonymous ArrayList, change its contents, and all other objects relying on the contents of that ArrayList will update accordingly, just like the Vector implementation does.
I was hoping someone could tell me why this is different, as both Vector and ArrayList implement List and supposedly should have similar behavior.
EDIT:
Thanks for the prompt responses! All answers refer to synchronization disparities between ArrayList and Vector. However, my project does not explicitly create new threads. Is it possible that this is a synchronization issue between my data and the Swing thread? I'm not good enough with threads to know...
2nd EDIT:
Thanks again everybody! The synchronization between data and Swing answers my question readily enough, though I'd still be interested in more details if there's more to it.
I suspect the difference is due to Vector being thread-safe and ArrayList not. This affects the visibility of changes to its elements to different threads. When you change an element in a Vector, the change becomes visible to other threads instantly. (This is because its methods are synchronized using locks, which create a memory barrier, effectively synchronizing the current state of the thread's memory - including the latest changes in it - with that of other threads.) However, with ArrayList such synchronization does not automatically happen, thus the changes made by one thread may become visible to other threads only later (and in arbitrary order), or not at all.
Since Swing is inherently multithreadedd, you need to ensure that data changes are visible between different (worker, UI) threads.
Vector is synchronized. It uses the synchronized keyword to ensure that all threads that access it see a consistent result. ArrayList is not synchronized. When one thread sets an element of an ArrayList there is no guarantee that another thread will see the update.
Access to Vector elements are synchronized, whereas its not for an ArrayList. If you have different threads accessing and modifying the lists, you will see different behavior between the two.
I don't have time to test this code, and your code sample is still really light (a nice fully functional sample would be more helpful - I don't want to write a full app to test this) but I'm willing to bet that if you wrapped your call to 'setSelectDeselect' (as shown in your pastebin) like this then ArrayList would work as well as Vector:
Runnable selectRunnable = new Runnable()
{
public void run()
{
setSelectDeselect(cat, itemName, selected);
}
};
SwingUtilities.invokeLater(selectRunnable);
You're updating your ArrayList in the middle of event processing. The above code will defer the update until after the event is complete. I suspect there's something else at play here that would be apparent from reviewing the rest of your code.

Java: a time-delayed queue that de-dupes

G'day everyone,
I have a system (the source) that needs to notify another system (the target) asynchronously whenever certain objects change. The twist is that the source system may mutate a single object many times in a short interval (updates are very "bursty"), and in that case it would be ideal to only notify the target system once, and with the final state of the object.
My thought was to use some kind of time-delayed, de-duping queue in front of a ThreadPoolExecutor for this. This queue would:
keep items on the queue for a minimum amount of time (ideally configured to be just a smidgin longer than the duration of a typical burst of mutations)
replace the existing object in the event that a duplicate (as defined by the object's identifier) is enqueued. The item should, however, retain its original place in the queue (to avoid any one item being perpetually bumped to the back of the queue - at some point we need to just send the notification even if another one will be coming along momentarily).
I haven't seen anything exactly like this in java.util, and my google-fu in this area appears to be particularly weak.
Has anyone implemented this before, know a BlockingQueue implementation that behaves this way, or have tips on how I might go about implementing one?
Thanks in advance!
Peter
PS. I know ESBs do this kind of thing, but that is too heavyweight an approach in this case - ideally I don't want to add any new library dependencies to the source system at all.
I think your best bet is to extend ArrayBlockingQueue and override offer and poll to add the time delay functionality.
Particularly ArrayBlockingQueue because it has a contains method.
Another idea is a DelayQueue where you override offer to remove the old element and insert the new but preserve the old time delay, which will essentially preserve order.
Then you need to wrap your queue items in a Delayed interface.
You could notify the system only that a change has occurred, and have the other system fetch the new state. Then don't notify of further changes until the state has been fetched.

Categories

Resources