2

I want to synchronize an object model in Android between two handler thread object. One object is "observable" and second is an observer. Both of them works in own threads infinitely. An observer register to observable by "registerListener" method and pass own reference and own Handler.

And observable object pass to their observers object model by theirs callback method (by handler). The object model is declared as "final", because I do not create infinitely new objects, but update its field with new values (getters and setters).

I do not want to pass object reference to observers (object is mutable) and I do not want to use "synchronized" keyword because I do not want to block threads.

So my idea is that I would create two same object models in "observable" object. Both of them would be "final", one of them would be used by "observable" object and would be changed in its thread, and the second would be changed based on first object in observer thread. Thus the object would be synchronized by observer handler. It is a good idea? I hope that my description is clear.

piotrpawlowski
  • 767
  • 2
  • 9
  • 19
  • It's usually wiser to find something suitable from java.util.concurrent (http://developer.android.com/reference/java/util/concurrent/package-summary.html) than roll your own synchronization system. See also http://developer.android.com/training/articles/smp.html – fadden Oct 11 '15 at 17:30

3 Answers3

1

In general, when you say "multithreading" you are implying "synchroniation", therefore your desire of not using synchronized keyword sounds strange to me. Now to your question...

If I understood correctly, you want to share some state (which is stored in "object model") between different threads, but without using synchronized keyword. Furthermore, your mention of I do not want to pass object reference to observers (object is mutable) hints that observers should not be able to modify the state of the object.

If the above description is correct, then you could copy your "object model" in "observable thread" and pass it to callbacks in "observer thread". Something along these lines (not tested):

private void notifyListeners() {
    for (int i=0; i<mListeners.size(); i++) {
        final ObjectModel copyModel = new ObjectModel(mModel); // Assuming copy-constructor exists
        mHandlers.get(i).post(new Runnable{
            mListeners.get(i).notify(copyModel);
        });
    }
}

Please note that there are drawbacks to this approach:

  1. Once copy-constructed, the objects passed to your listeners no longer "track" the state of the observable. This means that your listeners could be working on outdated data.
  2. You copy your "object model" for each listener on each invocation of notifyListeners method. This might become a major overhead (depending on the size of the model, the amount of listeners and the rate of notifications)
  3. If you will want your listeners to be able to modify the model in the future, you'll need to change your code completely.

Due to above reasons, I would advice against usage of the above approach, except for the simplest cases. In other cases, I would pass the original object to listeners and ensure thread safety. Few notes that can help you:

  1. In order to prevent listeners from modifying the model, you could employ Interface Segregation Principle. The general idea: define two separate interfaces - one for reading the state of the model, and the other one for altering this state (e.g. WritableModel and ReadableModel). Make your "object model" implement both, and then pass this model to listeners as ReadableModel. This way you'll expose the listeners only to the non-mutating API of your model.
  2. Since there is only one thread that can alter the state of the model, you could make use of volatile members instead of full synchronization schemes. This will reduce the need for synchronized blocks. Please keep in mind that while volatile keyword resolves visibility issues, it does not address atomicity problems (i.e. you'll still need to use synchronized for members of the model which are not written atomically).
  3. Instead of synchronizing the non-atomically written members yourself, you could make use of the classes found in java.util.concurrent.atomic package.
Vasiliy
  • 16,221
  • 11
  • 71
  • 127
0

You can try EveyBus: https://github.com/greenrobot/EventBus Create you own event with object. like this EventBus.getDefault().post(new MyEventResult());

Alex
  • 1
  • 1
0

I think that the best option is using ThreadLocal object and having instance of obejct model for each thread.

piotrpawlowski
  • 767
  • 2
  • 9
  • 19