How to properly do a thread callback in Java?

I am working on a project in Java (no Android). I have a thread that does some long work and I want a function in the main thread to be called when the work is done. I’ve seen many questions already speaking of this issue, but no answer seems to be working. My current implementation looks like the following:

  • Have an interface with a callback function in it
  • Take that interface as a parameter in the runnable
  • Implement it in the main class, and then create the runnable and start a new thread.
  • On the callback function, print the current threads name

This is not working, as when the thread finishes, it always prints the name of the new thread, not the main one. How can I make the callback function be called on the main thread and not the new thread?

Thanks!

EDIT: This is the code that I have tried:

import java.util.Random;

public class ATestThreadClass {
    public static void main(String[] args) {
        new Thread(new RandomRunnable(data -> {
        System.out.println("Called on " + Thread.currentThread().getName());
        System.out.println(data.toString());
    })).start();
}

    static class RandomRunnable implements Runnable {
    private final CallbackInterface callbackInterface;

    public RandomRunnable(CallbackInterface callbackInterface) {
        this.callbackInterface = callbackInterface;
    }

    @Override
    public void run() {
        // Do some very long work...
        Random random = new Random();
        RandomCallbackData data = new RandomCallbackData();
        data.a = random.nextInt(100);
        data.b = random.getClass().getSimpleName();
        data.c = random.nextLong();
        callbackInterface.callback(data); // THIS REALLY NEEDS TO BE CALLED ON THE MAIN THREAD
    }
}


interface CallbackInterface {
    void callback(RandomCallbackData data);
}

static class RandomCallbackData {
    public int a;
    public String b;
    public long c;

    @Override
    public String toString() {
        return "RandomCallbackData{" +
                "a=" + a +
                ", b='" + b + ''' +
                ", c=" + c +
                '}';
        }
    }
}

(Sorry for weird formatting; stack overflow messes it up when I paste in the code)

And the following is the log:

Called on Thread-3
RandomCallbackData{a=77, b='Random', c=-7871432476136355770}

Process finished with exit code 0

Answer

The following may not be the best possible answer, so if there is something better, please correct me. This my code:

Main Class:
https://pastebin.com/hSZjGWsr

Holder class for tasks:
https://pastebin.com/eme9nqtA

Callback code:
https://pastebin.com/JvXadT0L

Worker thread code:
https://pastebin.com/fZYdfn9m

A lot of this can be done in pure java, but writing it all by hand makes it easier to understand.

The following is a summary of how it works:

  • There is a worker thread class. When you call the method .get(), the thread returns the final value. You can also call .isDone() to figure out if the thread has finished.
  • A list stores a holder class which keeps track of the worker thread and it’s callback. The method update is meant to be called in a loop.
  • When a thread is done, the corresponding callback is called with its return value. The thread is then stopped and the task is removed from the list.
  • You can define how often the tasks are checked for competition. If your application requires the callbacks to be called right away, pass in 0 or 1 as the first parameter in the constructor. Otherwise, pass in how quickly you want things to update in milliseconds.
  • You should call the method markComplete when you won’t be using the system anymore.

For more infomation on how it works, see the comments that I put in the code.

I understand that my implementation requires a loop, meaning that it’s not the best possible option. This is the only way that I can think of though. Again, please correct me if there is a better way.

Hope this helps! 😉