2

我有一堆程序需要连续执行,直到它们全部执行,或者满足某个条件。这是在满足条件之前需要执行的基本代码:

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参数 togo()和指示它们应该立即返回,spin()以便检查条件。然而,这种方法让我觉得效率很低,因为同一个代码块必须重复 10 次。这可以通过异常或并发线程更有效地实现吗?

4

4 回答 4

3

不知道你为什么要使用Thread.yield()- 是否有其他你没有提到的线程正在执行?或者,也许我误读了这个问题。

我想也许命令模式可以在这里工作。您将拥有一个RobotCommand带有execute方法的接口,以及RobotCommand每个命令类型(go、spin 等)的实现。然后你可以将 a 构造RobotAlgorithm为 a Listof RobotCommand,并有一个executeRobotAlgorithm迭代列表的方法,调用execute每个RobotCommand并检查每个thingFound()之后的结果。

编辑- 哦,我想我明白了。执行gospin启动改变机器人状态的线程,或类似的东西?

编辑 2 - 回应您的评论,听起来这里的问题是,如果机器人找到它正在寻找的东西,您需要能够立即返回,但是go,spin等命令现在不会这样做,而您需要同时继续执行新命令的能力。所以我可能在这里做的是有两个线程——一个是一个“执行器”线程,它会一个接一个地执行你ListRobotCommands,另一个是一个“观察者”线程,它会反复休眠和轮询(检查thingFound())。如果thingFound()是真的,那么你可以停止你的机器人以及执行器线程,或者如果执行器在thingFound()为真之前到达终点,那么它可以发出这样的信号(如有必要)。

于 2010-01-09T19:03:03.500 回答
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 编程而言,指向函数的指针)。 我怀疑你可以,但我不知道语法和规则。证据似乎是你不能(无论如何,大约在 2004 年) 。

于 2010-01-09T19:14:32.070 回答
0

基于 Jonathan Leffler 的回答
您可以使用 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 */);
}
于 2010-01-09T23:53:03.693 回答
0

机器人可以使用 Condition 对象向控制器发出信号,表明它已完成某些子任务或进入新状态:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/Condition.html

有趣的是,对于您所处的环境,您可能可以使用 and notify()wait()而不是更灵活的 Condition。控制器可以 wait() 直到机器人决定用 notify() 释放他。

于 2010-01-09T19:09:40.643 回答