Domanda

Ho un sacco di procedure che devono essere eseguiti in successione fino a quando sono tutti eseguiti, o di una certa condizione è soddisfatta. Ecco il codice di base che deve essere eseguito fino a quando una condizione è soddisfatta:

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
}

Finora, l'unico modo che ho pensato di fare quello che volevo è questo:

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
}

Il parametro false a go() e spin() indica che dovrebbero tornare immediatamente, permettendo la condizione da controllare. Tuttavia, questo approccio mi sembra piuttosto inefficiente, come lo stesso blocco di codice deve essere ripetuto 10 volte. Questo potrebbe essere raggiunto in modo più efficiente con eccezioni o thread simultanei?

È stato utile?

Soluzione

di Jonathan Leffler :
è possibile utilizzare un Runnable come puntatore per i comandi

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
}


un ulteriore passo, se del caso, si inserisce il Comandi in una matrice o un elenco ed eseguirlo come uno 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 */);
}

Altri suggerimenti

Ci sono altri thread esecuzione che lei non ha citato -

Non certo perché si sta utilizzando Thread.yield()? O forse ho letto male il problema.

Credo che forse il modello di comando potrebbe lavorare qui. Si avrebbe un'interfaccia RobotCommand con un metodo execute, e l'implementazione di RobotCommand per tipo di comando (andare, rotazione, ecc). Poi si potrebbe costruire un RobotAlgorithm come List di RobotCommand, e avere un metodo che executeRobotAlgorithm iterato sopra la lista, chiamando execute su ogni RobotCommand e controllo il risultato della thingFound() dopo ciascuno di essi.

Modifica - oh, penso ho capito. Non go e spin kick off le discussioni che modificano lo stato del robot, o qualcosa di simile?

Modifica 2 - in risposta al tuo commento, suona come il problema qui è che è necessario essere in grado di restituire immediatamente se il robot trova ciò che sta cercando, ma la go, spin, ecc comandi non farlo in questo momento, ed è necessario la capacità di mantenere l'esecuzione di nuovi comandi nel frattempo. Allora, cosa potrei fare qui è di avere due thread - uno sarebbe un filo "esecutore" che eseguirà il vostro List di RobotCommands uno per uno, e un filo di "osservatore" che più volte dormire e sondaggio (controllare thingFound()). Se thingFound() è mai vero, allora ci si può fermare il robot, così come il filo esecutore, o se l'esecutore arriva alla fine prima di thingFound() è vero allora può segnalare come tale (se necessario).

Chiaramente, il ciclo while può essere confezionato in una sua funzione:

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
}

(non mi importa se il condizionale è divisa su due righe,., Probabilmente farei che nel codice di produzione)

Una migliore programmatori Java di quanto io posso dire se è possibile passare 'procedure' di tutto (puntatori a funzioni, in termini di programmazione C). Ho il sospetto è possibile, ma non so la sintassi e le regole. Il prove sembra essere che non è possibile (circa 2004, in ogni caso).

robot può utilizzare un oggetto condizione per segnalare al controller che è completato alcuni sub-task o inserito un nuovo stato:

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

interessante, per l'ambiente che è in voi potrebbe forse usare e notify () e wait () al posto della condizione più flessibile. Controller poteva aspettare () fino a quando il robot decide di liberarlo con la notifica ().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top