Frage

Ich habe eine Reihe von Verfahren, die nacheinander ausgeführt werden müssen, bis entweder alle ausgeführt werden oder eine bestimmte Bedingung erfüllt ist. Hier ist der grundlegende Code, der ausgeführt werden muss, bis eine Bedingung erfüllt ist:

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
}

Bisher habe ich nur daran gedacht, das zu tun, was ich wollte, folgendermaßen:

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
}

Das false Parameter zu go() und spin() Zeigt an, dass sie sofort zurückkehren sollten, sodass die Bedingung überprüft wird. Dieser Ansatz fällt mir jedoch als eher ineffizient an, da der gleiche Codeblock 10 -mal wiederholt werden muss. Könnte dies mit Ausnahmen oder gleichzeitigen Threads effizienter erreicht werden?

War es hilfreich?

Lösung

Basierend auf Jonathan Leffler's Antworten:
Sie können einen Runnable als verwenden Zeiger zu den Befehlen

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
}


Ein weiterer Schritt, falls zutreffend, setzen Sie die Befehle in einem Array oder einer Liste und führen Sie es als Skript aus

...

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

Andere Tipps

Ich bin mir nicht sicher, warum Sie es verwenden Thread.yield() - Gibt es andere Themen, die Sie nicht erwähnt haben? Oder vielleicht habe ich das Problem falsch verstanden.

Ich denke, vielleicht könnte das Befehlsmuster hier funktionieren. Sie hätten eine RobotCommand Schnittstelle mit an execute Methode und eine Implementierung von RobotCommand pro Befehlstyp (Go, Spin usw.). Dann könntest du a konstruieren RobotAlgorithm Als ein List von RobotCommand, und haben eine Methode executeRobotAlgorithm das über die Liste iteriert, rufe an execute auf jeder RobotCommand und das Ergebnis von Überprüfen thingFound() nach jedem.

Bearbeiten - Oh, ich glaube, ich verstehe es. Tun go und spin Fäden starten, die den Zustand des Roboters oder so etwas verändern?

Bearbeiten 2 - Als Antwort auf Ihren Kommentar klingt das Problem hier, dass Sie sofort zurückkehren müssen, wenn der Roboter findet, wonach er sucht, aber der go, spin, usw. Befehle werden dies momentan nicht tun, und Sie benötigen die Möglichkeit, in der Zwischenzeit weiterhin neue Befehle auszuführen. Ich könnte hier also zwei Threads haben - einer wäre ein "Executor" -Thread, der Ihre ausführen würde List von RobotCommands einzeln und ein "Beobachter" -Faden, der wiederholt schlafen und abfragt thingFound()). Wenn thingFound() Ist jemals wahr, dann können Sie Ihren Roboter sowie den Executor -Thread stoppen oder wenn der Testamentsvollstrecker zuvor am Ende kommt thingFound() Ist wahr, dann kann es als solche signalisieren (falls erforderlich).

Die while -Schleife kann eindeutig in seine eigene Funktion verpackt werden:

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
}

(Ich habe nichts dagegen, ob die Bedingung über zwei Zeilen geteilt wird. Ich würde das wahrscheinlich im Produktionscode tun.)

Ein besserer Java -Programmierer, als ich Ihnen sagen kann, ob Sie 'Verfahren' umgeben können (Hinweise auf Funktionen, in Bezug auf C -Programmierung). Ich vermute, Sie können, aber ich kenne die Syntax und die Regeln nicht. Das Beweis scheint zu sein, dass du nicht kannst (um 2004 sowieso).

Roboter kann ein Bedingungsobjekt verwenden, um dem Controller zu signalisieren, dass er einige Unteraufgaben abgeschlossen hat oder einen neuen Zustand eingegeben hat:

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

interessant, für die Umgebung, in der Sie wahrscheinlich verwenden könnten und benachrichtigen() und Warten() anstelle des flexibleren Zustands. Controller könnte warten (), bis der Roboter beschließt, ihn mit Notify () freizulassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top