Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is this implementation thread safe? #28

Open
ysyyork opened this issue May 13, 2017 · 3 comments
Open

Is this implementation thread safe? #28

ysyyork opened this issue May 13, 2017 · 3 comments

Comments

@ysyyork
Copy link

ysyyork commented May 13, 2017

I plan to use dispatch action from a background service within a different thread. Is this implementation thread safe or I have to do it myself? Thanks.

@ysyyork ysyyork changed the title Is this implementation multi-thread safe? Is this implementation thread safe? May 13, 2017
@Yarikx
Copy link
Owner

Yarikx commented May 15, 2017

Hi @ysyyork

The short answer is YES, the implementation should be thread safe. Each action is applied to reduce function guarded by synchronised block. So you can dispatch actions from any thread.

However, you may still have some problems with those. On each action, Reductor notifies all state listeners on the thread where the action was applied. That might be the problem sometimes, for example:

In Activity, UI code is listening for state updates and render it on each update.
If you will send any action from a background thread (for instance when data is loaded from a network) - render will also be executed from that thread, leading to updating a UI not in main thread.

Usually, I solve that problem by enforcing all the actions to be propagated through Main Thread.
I use simple middleware to do that:

public class MainThreadMiddleware<T> implements Middleware<T> {
    private final Handler handler;
    private MainThreadMiddleware() {
        handler = new Handler(Looper.getMainLooper());
    }

    public static <T> MainThreadMiddleware<T> create() {
        return new MainThreadMiddleware<>();
    }

    @Override
    public Dispatcher create(Store<T> store, Dispatcher nextDispatcher) {
        return action -> {
            if (Looper.myLooper() != Looper.getMainLooper()) {
                handler.post(() -> nextDispatcher.dispatch(action));
            } else {
                nextDispatcher.dispatch(action);
            }
        };
    }
}

The idea is simple: if action is dispatched from other thread then Main looper - re-dispatch it!
So now I do not need to care about where to dispatch an action. I still need to care about not doing blocking operation in .subscribe(listener) method, but that's where RxJava can help with .observeOn(scheduler) method.

@ysyyork
Copy link
Author

ysyyork commented May 15, 2017 via email

@devhed
Copy link

devhed commented Dec 15, 2017

Any suggestions on how to propagate actions dispatched from a background worker thread to the main thread for non-Android specific Java projects?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants