Pergunta

Eu tenho vários procedimentos que precisam ser executados sucessivamente até que todos sejam executados ou uma certa condição seja atendida. Aqui está o código básico que precisa ser executado até que uma condição seja atendida:

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
}

Até agora, a única maneira de pensar em fazer o que queria é isso:

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
}

o false parâmetro para go() e spin() indica que eles devem retornar imediatamente, permitindo que a condição seja verificada. No entanto, essa abordagem me parece bastante ineficiente, pois o mesmo bloco de código deve ser repetido 10 vezes. Isso poderia ser alcançado com mais eficiência com exceções ou encadeamentos simultâneos?

Foi útil?

Solução

baseado no Jonathan Leffler responda:
você pode usar um executável como ponteiro para os comandos

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
}


um passo adicional, se apropriado, coloque o comandos em uma matriz ou lista e executá -la como um script

...

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 */);
}

Outras dicas

Não sei por que você está usando Thread.yield() - Existem outros tópicos que você não mencionou? Ou talvez eu interprete o problema.

Eu acho que talvez o padrão de comando possa funcionar aqui. Você teria um RobotCommand Interface com um execute método e uma implementação de RobotCommand por tipo de comando (vá, spin, etc). Então você pode construir um RobotAlgorithm como um List do RobotCommand, e tem um método executeRobotAlgorithm que iterou sobre a lista, chamando execute em cada RobotCommand e verificando o resultado de thingFound() depois de cada um.

Editar - Oh, acho que entendi. Fazer go e spin Inicie os tópicos que mudam o estado do robô, ou algo assim?

Editar 2 - Em resposta ao seu comentário, parece que o problema aqui é que você precisa poder retornar imediatamente se o robô encontrar o que está procurando, mas o go, spin, os comandos etc não farão isso agora e você precisa da capacidade de continuar executando novos comandos enquanto isso. Então, o que eu poderia fazer aqui é ter dois tópicos - um seria um tópico de "executor" que executaria seu List do RobotCommandS um por um, e um tópico "Watcher" que vai dormir e pesquisar repetidamente (verifique thingFound()). Se thingFound() é sempre verdade, então você pode parar seu robô, bem como o tópico do executor, ou se o executor chegar ao fim antes thingFound() é verdade, então ele pode sinalizar como tal (se necessário).

Claramente, o loop do tempo pode ser embalado em sua própria função:

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
}

(Não me importo se o condicional estiver dividido em duas linhas; eu provavelmente faria isso no código de produção.)

Um melhor programador Java do que posso dizer se você pode passar 'procedimentos' (ponteiros para funções, em termos de programação C). Suspeito que você possa, mas não conheço a sintaxe e as regras. o evidência Parece que você não pode (por volta de 2004, de qualquer maneira).

O robô pode usar um objeto de condição para sinalizar ao controlador que ele concluiu alguma subjuga ou entrou em um novo estado:

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

interessante, para o ambiente que você provavelmente poderia usar e notificar () e esperar() em vez da condição mais flexível. O controlador poderia esperar () até que o robô decida libertá -lo com notify ().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top