Question

J'ai un tas de procédures qui doivent être exécutées successivement jusqu'à ce qu'ils soient tous exécutés, ou une certaine condition est remplie. Voici le code de base qui doit être exécutée jusqu'à ce qu'une condition soit remplie:

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
}

Jusqu'à présent, la seule façon que je l'ai pensé à faire ce que je voulais est la suivante:

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
}

Le paramètre false à go() et spin() indique qu'ils doivent retourner immédiatement, ce qui permet la condition à vérifier. Cependant, cette approche me semble plutôt inefficace, car le même bloc de code doit être répété 10 fois. Cela pourrait-il être réalisé de manière plus efficace avec des exceptions ou threads simultanés?

Était-ce utile?

La solution

basé sur Jonathan Leffler réponse :
vous pouvez utiliser un Runnable comme pointeur aux commandes

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
}


une étape supplémentaire, le cas échéant, mettre le commandes dans un tableau ou une liste et l'exécuter comme un 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 */);
}

Autres conseils

Je ne sais pas pourquoi vous utilisez Thread.yield() - qu'il ya d'autres threads d'exécution que vous n'avez pas parlé? Ou peut-être mal lu le problème.

Je pense que peut-être le modèle de commande pourrait fonctionner ici. Vous auriez une interface RobotCommand avec une méthode execute, et une mise en œuvre de RobotCommand par type de commande (aller, rotation, etc.). Ensuite, vous pouvez construire un RobotAlgorithm comme List de RobotCommand, et ont une executeRobotAlgorithm de méthode qui itéré la liste, appelant execute sur chaque RobotCommand et vérifier le résultat de thingFound() après chacun.

Modifier - oh, je pense que je l'obtiens. Est-ce go et spin coup d'envoi des fils qui changent l'état du robot, ou quelque chose comme ça?

Edit 2 - en réponse à votre commentaire, il semble que le problème ici est que vous devez être en mesure de revenir immédiatement si le robot trouve ce qu'il cherche, mais le go, spin, etc commandes ne le feront pas en ce moment, et vous avez besoin la possibilité de poursuivre l'exécution de nouvelles commandes dans l'intervalle. Donc ce que je pourrais faire ici est d'avoir deux fils - l'un serait un fil « exécuteur » qui exécute votre List de RobotCommands un par un, et un fil « guetteur » qui dormira à plusieurs reprises et sondage (vérifier thingFound()). Si thingFound() est toujours vrai, alors vous pouvez arrêter votre robot ainsi que le fil d'exécuteur testamentaire, ou si l'exécuteur arrive à la fin avant thingFound() est vrai il peut alors signaler en tant que tel (le cas échéant).

Il est clair que la boucle while peut être emballé dans sa propre fonction:

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
}

(je ne me dérange pas si le conditionnel est réparti sur deux lignes,. Je ferais probablement que dans le code de production)

Un meilleur programmeur Java que je ne peux vous dire si vous pouvez passer les « procédures » autour (des pointeurs vers des fonctions, en termes de programmation C). Je suppose que vous pouvez, mais je ne sais pas la syntaxe et les règles. preuves semble que vous ne pouvez pas (vers 2004, de toute façon).

robot peut utiliser un objet de condition pour signaler au contrôleur qu'il a terminé une sous-tâche ou est entré dans un nouvel état:

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

intéressant, pour l'environnement qui est en vous pouvez probablement utiliser et notify () et attente () au lieu de la condition plus souple. contrôleur pourrait attendre () jusqu'à ce que le robot décide de le libérer avec notify ().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top