Java – With Guava’s EventBus, can I run subscriber code on the thread that created the bus?

With Guava’s EventBus, can I run subscriber code on the thread that created the bus?… here is a solution to the problem.

With Guava’s EventBus, can I run subscriber code on the thread that created the bus?

With Guava’s EventBus, I want to be able to post from a background thread (called “background”) to a specific thread (in this case, thread “main”) that updates the UI. I think the following would work, but this would call the subscriber code from a background thread:

package com.example;

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.util.concurrent.MoreExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EventBusTester {

    private static final Logger log = LoggerFactory.getLogger(EventBusTester.class);

    public static void main(String... args) {
        new EventBusTester().run();
    }

    private void run() {
        log.info("Starting on thread {}.", Thread.currentThread().getName());

        final EventBus eventBus = new AsyncEventBus(MoreExecutors.sameThreadExecutor());
        eventBus.register(this);

        Thread background = new Thread(new Runnable() {
            @Override
            public void run() {
                long now = System.currentTimeMillis();
                eventBus.post(now);
                log.info("Posted {} to UI on thread {}.", now, Thread.currentThread().getName());
            }
        }, "background");
        background.start();
    }

    @Subscribe
    public void updateUi(Long timestamp) {
        log.info("Received {} on UI on thread {}.", timestamp, Thread.currentThread().getName());
    }
}

This will print the following:

02:20:43.519 [main] INFO  com.example.EventBusTester - Starting on thread main.
02:20:43.680 [background] INFO  com.example.EventBusTester - Received 1387848043678 on UI on thread background.
02:20:43.680 [background] INFO  com.example.EventBusTester - Posted 1387848043678 to UI on thread background.

So my question is:

  1. Is it possible to do what I want, such as using an ExecutorService that I somehow missed, or writing a custom ExecutorService, or
  2. Do I need some other libraries to do this? For example. Square’s Otto (because I’ll use it on Android too).

I’d rather stay at pure Guava, though.

Thank you!

Solution

EventBus If you use an instance, the method executes on the same thread that publishes the @Subscribe event.

If you want to do something different, use AsyncEventBus, where you can provide a Executor to define the exact behavior when the event is published.

For example, on Android, to have each @Subscribe method run on the main thread, you can do the following:

EventBus eventBus = new AsyncEventBus(new Executor() {

    private Handler mHandler;

    @Override
    public void execute(Runnable command) {
        if (mHandler == null) {
            mHandler = new Handler(Looper.getMainLooper());
        }
        mHandler.post(command);
    }
});

Looper.getMainLooper() Returns the main looper for the application, which is on the application’s main thread.

Related Problems and Solutions