Как я могу прервать последовательность процедур в Java? - PullRequest
2 голосов
/ 09 января 2010

У меня есть куча процедур, которые должны выполняться последовательно, пока они не будут выполнены или не выполнено определенное условие. Вот базовый код, который необходимо выполнить, пока не будет выполнено условие:

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() и spin() указывает, что они должны немедленно вернуться, что позволяет проверить условие. Однако такой подход кажется мне довольно неэффективным, поскольку один и тот же блок кода должен повторяться 10 раз. Может ли это быть достигнуто более эффективно с помощью исключений или одновременных потоков?

Ответы [ 4 ]

3 голосов
/ 09 января 2010

Не уверен, почему вы используете Thread.yield() - существуют ли другие потоки, которые вы не упомянули? Или, может быть, я неправильно понял проблему.

Я думаю, что здесь может подойти шаблон Command. У вас будет интерфейс RobotCommand с методом execute и реализация RobotCommand для каждого типа команды (go, spin и т. Д.). Тогда вы могли бы создать RobotAlgorithm как List из RobotCommand и иметь метод executeRobotAlgorithm, который выполняет итерацию по списку, вызывая execute для каждого RobotCommand и проверяя результат thingFound() после каждого один.

Редактировать - О, я думаю, я понял. go и spin запускают темы, которые меняют состояние робота, или что-то в этом роде?

Редактировать 2 - в ответ на ваш комментарий звучит так, что проблема в том, что вам нужно иметь возможность немедленно вернуться, если робот найдет то, что он ищет, но go, spin, и т. Д. Команды не будут делать это прямо сейчас, и вам нужна возможность продолжать выполнять новые команды в то же время. Итак, что я мог бы сделать, это иметь два потока - один из них был бы потоком-исполнителем, который будет выполнять ваши List из RobotCommand -ов, один за другим, и поток-наблюдатель, который будет многократно спать и опрашивать (check thingFound()). Если thingFound() когда-либо имеет значение true, тогда вы можете остановить своего робота, а также поток исполнителя, или, если исполнитель завершит работу до того, как thingFound() станет истиной, тогда он может подать сигнал как таковой (при необходимости).

2 голосов
/ 09 января 2010

Понятно, что цикл 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, во всяком случае).

0 голосов
/ 10 января 2010

на основе ответа Джонатана Леффлера :
Вы можете использовать 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 */);
}
0 голосов
/ 09 января 2010

робот может использовать объект Condition, чтобы сообщить контроллеру, что он выполнил некоторую подзадачу или вошел в новое состояние:

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

интересно, для среды, которую вы можете, вероятно, использовать и notify () и wait () вместо более гибкого условия. контроллер может ждать (), пока робот не решит отпустить его с уведомлением ().

...