我有一个方法需要一段时间才能完成。我希望我的方法在返回“最终”结果之前返回“初步”结果。
我想了解是否可以这样:
public Object myMethod () {
/*some computation here*/
return firstResult;
/*
very long computation here
*/
return finalResult;
}
这是否可行,或者您可以建议某种解决方法吗?
答案 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)
这是可能的,但你必须介绍线程。
您的应用程序应该有两个线程main
和worker
。
main
主题,是你的整个程序。在他的工作期间开始worker
。工作人员进行计算,在第一部分之后,他可以设置main
线程可以读取和显示的值。