Return multiple times from a method? Return multiple times from a method? multithreading multithreading

Return multiple times from a method?


You could put the long-running task on an executor (which would execute the task asynchronously using a thread pool) and return a Future that you can use later to get the answer. When you call get on the future, it blocks until the task finishes, so you can use your initial answer right away and call Future.get when you need more precision later, having given the task some time to finish.

The return value might look like this:

class MyMethodReturnStuff {    private Object quickAnswer;    private Future longAnswer;    private long startTime = System.currentTimeMillis();    MyMethodReturnStuff(Object quickAnswer, Future longAnswer) {        this.quickAnswer = quickAnswer;        this.longAnswer = longAnswer;    }    Object getAnswer(long expectedDelay) {        return System.currentTimeMillis() - startTime < expectedDelay ?        quickAnswer : longAnswer.get();    }}

If you expect the long calculation to take 5 seconds, calling getAnswer(5000) would return the quick answer if less than 5 seconds has passed and would return the longAnswer otherwise.


Couldn't you simply use two different methods?

public class Computer {    private String commonVar1;    private int commonVar2;    public Object shortComput() {        // short comput using commonVar1 and commonVar2        return firstResult;    }    public Object longComput() {        // long comput using commonVar1 and commonVar2        return finalResult;    }}

When calling:

Computer c = new Computer();Object firstResult = c.shortComput();// do some short stuff with firstResult before launching:Object finalResult = c.longComput();


Yes. SwingWorker is the way to go.

If you're not familiar with SwingWorker, it's basically a class that lets you have long-running computations running. They can give a result when they're done or publish interim results along the way, which is basically what you're trying to do.

From "Tasks that Have Interim Results," a section of the Java Tutorial:

It is often useful for a background task to provide interim results while it is still working. The task can do this by invoking SwingWorker.publish. This method accepts a variable number of arguments. Each argument must be of the type specified by SwingWorker's second type parameter.

For example:

private class FlipTask extends SwingWorker<Void, FlipPair> {    @Override    protected Void doInBackground() {        long heads = 0;        long total = 0;        Random random = new Random();        while (!isCancelled()) {            total++;            if (random.nextBoolean()) {                heads++;            }            // Here's your interim result, your "first return statement"            publish(new FlipPair(heads, total));                    }        return null;    }    @Override    protected void process(List<FlipPair> pairs) {        FlipPair pair = pairs.get(pairs.size() - 1);        headsText.setText(String.format("%d", pair.heads));        totalText.setText(String.format("%d", pair.total));        devText.setText(String.format("%.10g",                 ((double) pair.heads)/((double) pair.total) - 0.5));    }}

If for some reason you can't use SwingWorker, you'd need to use asynchronous threads to do this. You could try something like:

interface Callback {    public void computationComplete(Result r);}public Result doComputation(final Callback c) {    // Do computation    new Thread(new Runnable() {        @Override        public void run() {            // Complete computation            c.computationComplete(finalResult);        }    }).start();    return firstResult;}

but this is basically reinventing the wheel.