我正在为类似国际象棋的游戏实施AI。我打算使用递归来尝试所有可能的董事会状态并选择“最佳动作”。
由于每次移动的时间限制,我需要有一些机制来在达到时间限制时中断这些递归过程。当然,我可以在进行递归调用之前继续检查时间,如果当前时间接近限制则会中断,但这是对我的程序性能的权衡。
如果有一种方法可以在计时器结束时突破那些递归过程,那将是很好的。但是,由于我是Java的新手,我不知道在java中是否有任何方法可以这样做?你能给出一个示例代码吗? :)
答案 0 :(得分:3)
检查时间,例如System.currentTimeMillis()每次调用大约需要200 ns。但是,如果这对你来说很重要,你可以让另一个线程设置一个标志来停止。
有一种机制可以做到这一点。
ExecutorService es = Executors.newSingleThreadExecutor();
Future f = es.submit(new Runnable() {
@Override
public void run() {
long start = System.nanoTime();
while(!Thread.interrupted()) {
// busy wait.
}
long time = System.nanoTime() - start;
System.out.printf("Finished task after %,d ns%n", time);
}
});
try {
f.get(1, TimeUnit.SECONDS); // stops if the task completes.
} catch (TimeoutException e) {
f.cancel(true);
}
es.shutdown();
打印
Finished task after 1,000,653,574 ns
注意:您不需要每次都启动/停止ExecutorService。
答案 1 :(得分:2)
我认为没有任何好办法可以不检查你是否可以继续。
即使您确实检查了时间......如果剩余8 milliseconds
会发生什么。你能保证你的递归通话会在那段时间内结束吗?你是否检查了每一小步后的时间(这可能会增加很多额外的开销)?
一种方法是让您的执行(递归)逻辑在一个线程中运行,并在另一个线程中运行一个计时器。当计时器完成时,它会在您的执行线程上调用interrupt()
。在工作线程中,每次完成递归时,都会保存所需的状态。然后,如果它被中断,则返回上次保存的状态。
这只是对一种方法的简要描述......绝不是最好的方式
答案 2 :(得分:0)
您可以使用布尔标志来设置AI任务必须停止的时间。
创建一个将运行AI任务的线程,该线程将在每次递归调用之前检查一个布尔变量。检查布尔变量比调用方法来获取时间更有效。父线程是否在有限的时间内休眠。唤醒后,设置布尔标志以停止子线程。