2010-01-09 13 views
2

J'ai un tas de procédures qui doivent être exécutées successivement jusqu'à ce qu'elles soient toutes exécutées ou qu'une certaine condition soit remplie. Voici le code de base qui doit être exécutée jusqu'à ce qu'une condition soit remplie:Comment puis-je interrompre une séquence de procédures en Java?

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 ceci:

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 false paramètre à go() et spin() indique qu'ils devraient retourner immédiatement, permettant à la condition d'être vérifiée. 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é plus efficacement avec des exceptions ou des threads concurrents?

+0

Voulez-vous ces boucles while to t sortir après un certain temps? –

+0

Non. Ils devraient continuer jusqu'à ce que 'robot.isMoving()' retourne 'false', car c'est seulement alors que la commande précédente est terminée. – Eric

Répondre

0

basé sur Jonathan Leffler answer:
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 les commandes dans un tableau ou une Répertoriez-le et exécutez-le en tant que 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 */); 
} 
3

Vous ne savez pas pourquoi vous utilisez Thread.yield() - Existe-t-il d'autres threads que vous n'avez pas mentionnés? Ou peut-être que j'ai mal interprété le problème.

Je pense que le modèle de commande pourrait fonctionner ici. Vous auriez une interface RobotCommand avec une méthode execute, et une implémentation de RobotCommand par type de commande (go, spin, etc.). Ensuite, vous pouvez construire un RobotAlgorithm comme List de RobotCommand, et une méthode executeRobotAlgorithm qui itéré la liste, appelant execute sur chaque RobotCommand et vérifier le résultat de thingFound() après chacun.

Édition - oh, je pense que je comprends. Est-ce que go et spin lancent des discussions 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, commandes, etc gagné » Pour le moment, vous devez pouvoir continuer à exécuter de nouvelles commandes. Donc ce que je pourrais faire ici est d'avoir deux threads - l'un serait un thread "exécuteur" qui exécuterait votre List de RobotCommand s un par un, et un thread "observateur" qui dormira et pollera à plusieurs reprises (vérifier thingFound()). Si thingFound() est toujours vrai alors vous pouvez arrêter votre robot ainsi que le thread exécuteur, ou si l'exécuteur arrive à la fin avant que thingFound() ne soit vrai alors il peut signaler comme tel (si nécessaire).

+0

Si les commandes du robot sont des méthodes comme go(), spin() etc, vous pouvez utiliser la réflexion pour écrire les commandes, de sorte que le code sera plus court. –

+0

C'est exact. Lorsqu'il est appelé sans paramètre, le paramètre 'while (robot.isMoving()) Thread.yield();' est inclus dans les fonctions. Lorsqu'il est appelé avec 'true', le thread démarre, mais la procédure n'attend pas sa fin. Je n'avais pas pensé à utiliser une liste. – Eric

+0

Comment puis-je arrêter le thread? – Eric

0

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 wait() au lieu de la condition plus flexible. Le contrôleur pourrait attendre() que le robot décide de le libérer avec notify().

+0

Malheureusement, la classe Condition n'est pas disponible dans le sous-ensemble limité de Java avec lequel je dois jouer. Le langage que j'utilise (LeJOS-NXJ) est un sous-ensemble assez limité de Java pour un contrôleur de robot LEGO. – Eric

2

De toute évidence, 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 moi peut vous dire si vous pouvez passer des 'procédures' (des pointeurs vers des fonctions, en termes de programmation C). Je suppose que vous pouvez, mais je ne connais pas la syntaxe et les règles. Le evidence semble être que vous ne pouvez pas (vers 2004, de toute façon).

+0

@danben: merci pour la confirmation supplémentaire; Comme vous pouvez le voir, j'avais trouvé la même chose via une recherche fidèle sur Google. (Un jour, j'expérimenterai à nouveau avec Bing et je verrai si cela produirait une meilleure réponse - mais jusqu'ici, ça n'a rien fait pour moi.) Wolfram Alpha n'a jamais daigné reconnaître aucune de mes questions comme valide. , Je ne fais pas partie de leur public cible.) –

+0

Droit - au moment où j'ai laissé ce commentaire, vous n'aviez pas fait votre édition. Désolé si j'avais l'impression de marcher sur vos orteils. Tel est le chemin de SO. – danben

+0

NP danben - comme le chronométrage l'a montré, vous étiez en train de taper le commentaire (que je vois que vous avez maintenant supprimé, donc le timing ne s'affiche plus) alors que j'édiquais ma réponse. Ce que vous avez fait m'a épargné de devoir passer trop de temps à savoir si Java avait changé. J'ai essayé Bing; sur l'une des pages ultérieures (2 ou 3, je pense, comparé à mi-chemin sur la première page sur Google), trouvé des preuves plus récentes de la même chose. –