7

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

我想了解是否有可能这样做:

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

     return firstResult;

     /*
     very long computation here
     */

     return finalResult;
}

这甚至可能吗,或者您可以建议某种解决方法吗?

4

8 回答 8

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 秒,getAnswer(5000)如果不到 5 秒,调用将返回快速答案,否则将返回 longAnswer。

于 2013-03-29T16:11:34.627 回答
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();
于 2013-03-29T16:08:59.203 回答
2

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

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

  // very long computation here
  output.add(..);
}
于 2013-03-29T16:09:03.800 回答
2

是的。SwingWorker是要走的路。

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

来自Java 教程的“具有临时结果的任务”部分:

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

例如:_

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

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

于 2013-03-29T16:09:41.577 回答
1

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

于 2013-03-29T16:09:46.070 回答
1

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

于 2013-03-29T16:10:05.860 回答
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;
}

}
}

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

于 2013-03-29T16:14:46.010 回答
-2

这是可能的,但你必须引入线程。

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

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

于 2013-03-29T16:12:51.847 回答