这就是我想要做的。给定一个函数
public void foo() {
}
我希望在经过一段时间后结束。也就是说,想象这是某种随机生成器,它必须产生满足某些困难约束的随机对象,因此在给定的时间分配下它可能成功也可能不成功。也就是说,该函数实际上可能是这样的
public void foo() {
//task1
while(fails) {
//...
}
//task2
while(fails2) {
//...
}
//more tasks may follow, which use the data from the previous tasks to further try to satisfy difficult conditions
}
这只是一个例子。但重点是该函数包含许多while循环,许多测试用例以及大量繁重的计算。
目标:我希望能够说“运行foo(),如果已经过了4秒而foo()仍未完成,则立即停止foo()。” p>
我尝试了什么:我试图在foo()的几乎每一行都包含条件,看看已经过了多少时间,如果4秒钟过去了,则返回函数。但考虑到foo()有多复杂,这显然很难做到代码,因为这需要测试函数的每一行的时间。
我的思想逻辑:我认为这应该是可能的,因为有些函数会执行此类操作,无论状态如何都会终止代码,例如System.exit(1)。这就是主意。我希望能够从外部调用foo()函数终止。
答案 0 :(得分:4)
// foo method and global variables used
private static ArrayList<Integer> foo() {
// info class
class Info {
public boolean run, completed;
public ArrayList<Integer> list;
}
// declare info object, list
final Info info = new Info();
final Object wait = new Object();
// run a new thread
Thread t = new Thread(
new Runnable() {
// run method
@Override
public void run() {
// setup run
info.run = true;
info.completed = false;
info.list = new ArrayList<>();
// loop to modify list. Don't put a big piece of code that will
// take a long time to execute in here.
while(info.run) {
// example of what you should be doing in here:
info.list.add(1);
// and if you are done modifying the list, use:
break;
}
// done modifying list
info.completed = true;
synchronized(wait) {
wait.notify();
}
}
}
);
t.start();
// wait for four seconds, then return list
try {
synchronized(wait) {
wait.wait(4000);
}
} catch (InterruptedException e) { e.printStackTrace(); }
info.run = false;
return info.completed ? info.list : null;
}
// main method
public static void main(String[] args) {
// get list
ArrayList<Integer> list = foo();
System.out.println("Done!");
}
foo()方法的作用是什么?
答案 1 :(得分:2)
将其作为runnable提交给执行程序服务,并使用所需的超时调用返回的返回将来。然后在超时异常的catch块中,您可以取消将来。
编辑:代码示例
import com.google.common.base.Throwables;
import java.util.concurrent.*;
public class ExecutorExample {
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
public void example() {
Future<String> future = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "Do your complicated stuff";
}
});
try {
future.get(4, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (ExecutionException e) {
//handle
} catch (TimeoutException e) {
future.cancel(true);
}
}
}
答案 2 :(得分:1)
这样的事情可以解决问题,但要注意:
public static void main(String[] args){
Runnable fooRunner = new Runnable(){ public void run(){
foo();
}
Thread fooThread = new Thread(fooRunner);
fooThread.start();
Thread.sleep(4000);
fooThread.stop(); //warning -- this is deprecated!
}
问题在于Thread.stop
is deprecated。
Java中的多线程基本上是合作的努力。因为foo()
可能正在操纵共享状态,可能受其当前拥有的锁的保护,所以在任意点停止它可能非常危险,并且可能导致程序中的不可预测的故障,错误等。 (实际上,由于foo
的返回类型为void
,因此必须在某个时刻操作某些共享状态才能存储其结果。)
该语言确实提供了一种告诉线程它应该在下一个方便点停止的方法:Thread.interrupt()
,Thread.interrupted()
和InterruptedException
。您的foo()
方法确实需要检查它是否定期中断;这就是它的完成方式,任何更高级别的库构造(如Future.cancel()
)都依赖于此。
答案 3 :(得分:0)
你必须进入编写线程代码的地狱舞台。
http://docs.oracle.com/javase/tutorial/essential/concurrency/
伪代码(在apache commons http://commons.apache.org/lang/download_lang.cgi中可用的mutableboolean)
...
final MutableBoolean finished = new MutableBoolean(false);
new Thread(new Runnable(){
public void run() {
doComplicatedStuff(finished);
}
}).start();
Thread.sleep(4000);
finished.setValue(true);