Java Callback Execution in Thread Executed After run()

Eliezer picture Eliezer · May 9, 2014 · Viewed 8.3k times · Source

I'm using a job queue library, where you define Jobs and post them to a JobManager. The JobManager has a ThreadGroup with workers that pull Jobs off of a queue and call Job.onRun().

The amount of threads are set by giving a max and min amount of threads, a load factor (how many outstanding jobs can a worker thread have before creating a new one) and an idle timeout for any of the threads above min. Therefore, a worker thread's run() will terminate if it has no new jobs, and its idle timeout is reached.

In some Jobs I'm using libraries that only expose an async API. Is it safe to use these in onRun()?

For example, if I want to make a network request that takes a callback which provides me with a response will the callback get called:

@Override
public void onRun() throws Throwable {
    client.doRequest(request, new Callback() {
        @Override
        public void onRequestComplete(Response response) {
            //is this guaranteed to get called?
        }
    });
    //since we now return from onRun() will onRequestComplete() get called?
}

Answer

vkg picture vkg · May 10, 2014

Yes your callback will run as long as the process is still alive.

If you want to see I created a program to simulate just that. It has three classes just drop them in any one package and run and you will see your self. This depicts even when your job thread completes callback still comes. I hope it helps :)

Class 1

public class Client {
    private static long startTime = System.currentTimeMillis();

    public static void main(String[] args) {
        System.out.println("Time elapsed in ms:" + (System.currentTimeMillis() - startTime));
        Client client = new Client();
        client.executeJob();
        try {
            System.out.println("Main thread sleeping");
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Main thread finishing");
    }

    public void executeJob() {
        new Thread() {
            @Override
            public void run() {
                Job job = new Job();
                System.out.println("Calling Job with Asyc - Time elapsed in ms:" 
                        + (System.currentTimeMillis() - startTime));
                job.doRequest("Calling Async", new CallBack() {

                    @Override
                    public void onRequestComplete(String response) {
                        System.out.println("Got my callback eventhough job that started the Async is over - Time elapsed in ms:" 
                                + (System.currentTimeMillis() - startTime));
                    }
                });
                System.out.println("Job thread finishing");
            }
        }.start();
    }
}

Class 2

public abstract class CallBack {
    public abstract void onRequestComplete(String response);
}

Class 3

public class Job {
    public void doRequest(String request, final CallBack callBack){
        new Thread() {
            @Override
            public void run() {
                //Async Long running task
                try {
                    Thread.sleep(10000);
                    callBack.onRequestComplete("Long Async task Completed-- Sending response back");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }.start();
    }
}