从方法中多次返回?

时间:2013-03-29 16:05:01

标签: java multithreading concurrency return

我有一个方法需要一段时间才能完成。我希望我的方法在返回“最终”结果之前返回“初步”结果。

我想了解是否可以这样:

public Object myMethod () {
    /*some computation here*/

     return firstResult;

     /*
     very long computation here
     */

     return finalResult;
}

这是否可行,或者您可以建议某种解决方法吗?

8 个答案:

答案 0 :(得分:6)

您可以将长时间运行的任务放在执行程序上(使用线程池异步执行任务)并返回Future,以后可以使用它来获得答案。当您将来调用get时,它会一直阻止,直到任务完成,这样您就可以立即使用初始答案,并在以后需要更高精度时调用Future.get,让任务完成一段时间后完成。

返回值可能如下所示:

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();
    }
}

如果您希望长计算需要5秒钟,如果小于5秒,则调用getAnswer(5000)将返回快速答案,否则将返回longAnswer。

答案 1 :(得分:3)

难道你不能简单地使用两种不同的方法吗?

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;
    }

}

致电:

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

答案 2 :(得分:2)

不可能,函数只能返回一次。一旦它返回后续代码将不会被执行。但是,您可以更改代码设计,而不是将输出写入由参数/作为类成员放置的数据结构。例如:

public void longRunningFunc(List<String> output) {
  // some computation here
  output.add(..);

  // very long computation here
  output.add(..);
}

答案 3 :(得分:2)

是。 SwingWorker是要走的路。

如果您不熟悉SwingWorker,它基本上是一个允许您长时间运行计算的类。他们可以在完成或发布中期结果时给出结果,这基本上就是你想要做的。

来自{3}的Java教程的一部分:

  

后台任务在提供中间结果时仍然有用。该任务可以通过调用SwingWorker.publish来完成。此方法接受可变数量的参数。每个参数必须是SwingWorker的第二个类型参数指定的类型。

"Tasks that Have Interim Results,"

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));
    }
}

如果由于某种原因您无法使用SwingWorker,则需要使用异步线程来执行此操作。你可以尝试类似的东西:

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;
}

但这基本上是重新发明轮子。

答案 4 :(得分:1)

我会使用一个监听器模式。可以将自定义侦听器实例传递给方法或添加到对象。当长时间运行的方法执行时,您可以适当地调用侦听器,传递您需要的任何信息。这个监听器可以被多次调用。

答案 5 :(得分:1)

这在Java中绝对不可能。你为什么不简单地将你的方法分成两个不同的方法?

答案 6 :(得分:1)

只需使用条件:

public class TestMethod {


public static void main(String[] args)
{
boolean yes=false;
int something=compute(yes);
System.out.println(something);
yes=true;
something=compute(yes);
System.out.println(something);
}

public static int compute(boolean yes)
{
if(!yes)
{
    System.out.println("1st block");
return 22;
}
else
{
    System.out.println("2nd block");
return 33;
}

}
}

编辑: 我根据问题使用了一种方法:从方法中多次返回。

答案 7 :(得分:-2)

这是可能的,但你必须介绍线程。

您的应用程序应该有两个线程mainworker

main主题,是你的整个程序。在他的工作期间开始worker。工作人员进行计算,在第一部分之后,他可以设置main线程可以读取和显示的值。