我有一堆程序需要连续执行,直到它们全部执行或满足某个条件。这是在满足条件之前需要执行的基本代码:
public boolean search()
{
robot.go();
robot.spin();
//etc - around 8 more similar commands (each takes around 2 seconds)
return false; //didn't find what it was looking for
}
到目前为止,我想到做我想做的事的唯一方法是:
public boolean search()
{
robot.go(false);
while(robot.isMoving())
{
if(thingFound())
{
robot.stop()
return true;
}
Thread.yield();
}
robot.spin(false);
while(robot.isMoving())
{
if(thingFound())
{
robot.stop()
return true;
}
Thread.yield();
}
//etc - around 8 more similar commands
return false; //didn't find what it was looking for
}
false
和go()
的{{1}}参数表示它们应立即返回,以便检查条件。但是,这种方法对我来说效率相当低,因为相同的代码块必须重复10次。使用异常或并发线程可以更有效地实现这一点吗?
答案 0 :(得分:3)
不确定您使用Thread.yield()
的原因 - 是否有其他线程正在执行而您没有提及?或许我误解了这个问题。
我想也许Command模式可以在这里工作。您将拥有RobotCommand
接口和execute
方法,并且每个命令类型(go,spin等)实现RobotCommand
。然后,您可以将RobotAlgorithm
构建为List
RobotCommand
,并使用方法executeRobotAlgorithm
迭代列表,在每个{{1}上调用execute
每个人之后检查RobotCommand
的结果。
编辑 - 哦,我想我明白了。 thingFound()
和go
是否会启动改变机器人状态的线程,或类似的东西?
编辑2 - 为了回应您的评论,听起来这里的问题是,如果机器人找到了它正在查找的内容,您需要能够立即返回,但是{{1} },spin
等命令现在不会执行此操作,并且您需要能够在此期间继续执行新命令。所以我在这里可以做的是有两个线程 - 一个是“执行者”线程,它将逐个执行go
spin
个帖子,以及一个将重复睡眠的“观察者”线程民意调查(检查List
)。如果RobotCommand
为真,那么你可以停止你的机器人以及执行程序线程,或者如果执行程序在thingFound()
为真之前到达终点,那么它就可以发出信号(如果需要的话)。 / p>
答案 1 :(得分:2)
显然,while循环可以打包成自己的函数:
private boolean isFound()
{
while (robot.isMoving())
{
if (thingFound())
{
robot.stop()
return true;
}
Thread.yield();
}
return false;
}
public boolean search()
{
robot.go(false);
if (isFound()) return true;
robot.spin(false);
if (isFound()) return true;
//etc - around 8 more similar commands
return false; //didn't find what it was looking for
}
(我不介意条件是否分成两行;我可能会在生产代码中这样做。)
一个更好的Java程序员,我可以告诉你是否可以通过'程序'(指向函数,就C编程而言)。 我怀疑你可以,但我不知道语法和规则。 evidence似乎是你不能(大约2004年,无论如何)。
答案 2 :(得分:0)
机器人可以使用Condition对象向控制器发出信号,告知它已完成某个子任务或进入新状态:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/Condition.html
有趣的是,对于您可能使用的环境而言notify()和wait()而不是更灵活的条件。控制器可以等待()直到机器人决定用notify()释放他。
答案 3 :(得分:0)
基于Jonathan Leffler的answer:
您可以将Runnable作为指针用于命令
private final Runnable going = new Runnable() {
@Override
public void run() {
robot.go(false);
}
});
private final Runnable spinning = new Runnable {
@Override
public void run() {
robot.spin(false);
}
});
// other commands
private boolean isFoundAfter(Runnable command)
{
command.run();
while (robot.isMoving())
{
if (thingFound())
{
robot.stop()
return true;
}
Thread.yield();
}
return false;
}
public boolean search()
{
if (isFoundAfter(going)) return true;
if (isFoundAfter(spinning)) return true;
//etc - around 8 more similar commands
return false; //didn't find what it was looking for
}
如果合适,还可以将命令放在数组或列表中,并将其作为脚本执行
...
private boolean executeSearch(Runnable... commands)
{
for (Runnable cmd : commands) {
if (isFoundAfter(cmd)) return true;
}
return false; //didn't find what it was looking for
}
public boolean search() {
return executeSearch(going, spinning /* around 8 more similar commands */);
}