Call a listener method from a worker thread but have it run on the thread that added the listener

StackOverflow https://stackoverflow.com/questions/13875617

  •  07-12-2021
  •  | 
  •  

Question

I'm writing a TCP server class that I want to be self-contained. That is, the applications that use this class need not worry about the internal worker threads. The TCP server class has a start() method and I want to be able to call the listener's methods on the same thread that called start() (under normal use, the main thread). This is probably better explained with code:

public class ProblemExample {
    private Listener mListener;

    public ProblemExample() {
        mListener = new Listener() {
            @Override
            public void fireListener() {
                System.out.println(Thread.currentThread().getName());
            }
        };
    }

    public void start() {
        mListener.fireListener(); // "main" is printed
        new Thread(new Worker()).start();
    }

    public interface Listener {
        public void fireListener();
    }

    private class Worker implements Runnable {
        @Override
        public void run() {
            /* Assuming the listener is being used for status updates while
             * the thread is running, I'd like to fire the listener on the
             * same thread that called start(). Essentially, the thread that
             * starts the operation doesn't need to know or care about the
             * internal thread. */
            mListener.fireListener(); // "Thread-0" is printed
        }
    }
}

I've tried searching for this but I'm not really sure what to search for. The best I've found is that SwingWorker seems to do this, but I can't find out how.

Can anyone shed some light?

Was it helpful?

Solution

What you are asking for is theoretically impossible without explicit cooperation from the client thread (the one that called start()). Just stop to think about it: the main thread is always busy running some specific code, in some specific method. The complete call stack is dedicated to the current call. Now you would like to interrupt that and start executing listener code out of the blue.

The way Swing achieves this is by running a main event loop in the Event Dispatch Thread. In this loop, you can imagine instances of Runnable being pulled off of a queue and their run methods called in turn. Only when one run method returns can the next one be called.

This is what you need to design for your case as well, but I'm not sure whether you had something like that in mind. The only alternative is explicit support for listener methods being executed on a foreign thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top