Hallo!
Ja, ich schon wieder... Ich hoffe, ich nerv' euch nicht langsam, aber ich hänge schon wieder fest...
Ich habe eine Software programmiert bzw. bin dabei, die einen LEGO Mindstorms NXT-Roboter steuern kann. Hintergrund: Ich hab ein Boot gebaut, das über Bluetooth gesteuert wird und über das man via Unterwasserkamera Bilder in einem beliebigen Gewässer machen kann.
Jetzt erzeugen verschiedene Steuerungs-Schaltflächen und -Regler sowie mehrere laufende Aktualisierungen (Signalstärke, Akkustatus, Sensordaten, etc.) Steuerbefehle, die, um nicht bei der Übertragung zu kollidieren, an einen Thread übergeben werden, der die Befehle dann nacheinander sendet (und sich danach auch um die Umsetzung im UI kümmert).
Kommt jetzt ein neuer Eintrag in die Liste zur Abarbeitung, dann quittiert mir der Debugger das auch, und zwar so lange, wie die Methode zum Hinzufügen läuft. Beginnt der Thread dann mit der Abarbeitung (Prüfung auf size!=0 jede 1/2 Sekunde, nicht optimal, ich weiß), dann zeigt der Debugger an, die ArrayList sei leer. Was mache ich falsch?
Hier ist mein Code:
FindBugs habe ich übrigens schon drüber laufen lassen, der findet zwar was, aber nichts zu diesem Problem, außer "Write to static field ui.Remote.commandDispatcherv2Class from instance method new ui.Remote()". Aber das hat doch eigentlich nur mit der Initialisierung zu tun, oder?
Ja, ich schon wieder... Ich hoffe, ich nerv' euch nicht langsam, aber ich hänge schon wieder fest...
Ich habe eine Software programmiert bzw. bin dabei, die einen LEGO Mindstorms NXT-Roboter steuern kann. Hintergrund: Ich hab ein Boot gebaut, das über Bluetooth gesteuert wird und über das man via Unterwasserkamera Bilder in einem beliebigen Gewässer machen kann.
Jetzt erzeugen verschiedene Steuerungs-Schaltflächen und -Regler sowie mehrere laufende Aktualisierungen (Signalstärke, Akkustatus, Sensordaten, etc.) Steuerbefehle, die, um nicht bei der Übertragung zu kollidieren, an einen Thread übergeben werden, der die Befehle dann nacheinander sendet (und sich danach auch um die Umsetzung im UI kümmert).
Kommt jetzt ein neuer Eintrag in die Liste zur Abarbeitung, dann quittiert mir der Debugger das auch, und zwar so lange, wie die Methode zum Hinzufügen läuft. Beginnt der Thread dann mit der Abarbeitung (Prüfung auf size!=0 jede 1/2 Sekunde, nicht optimal, ich weiß), dann zeigt der Debugger an, die ArrayList sei leer. Was mache ich falsch?
Hier ist mein Code:
Java:
package communication;
import icommand.nxt.Sound;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class CommandDispatcher_v2 extends Thread {
private ArrayList<Command> commands = new ArrayList<Command>();
private boolean ignoreNew = false;
private boolean breakRequested = false;
private int commandCount = 0;
@Override
public void run()
{
try
{
while (!isInterrupted())
{
System.out.println("check commands list");
// Prüfen, ob es "etwas zu tun" gibt
if (commands.size() != 0)
{
// Alles abarbeiten, bis es nichts mehr zu tun gibt
while (commands.size() != 0)
{
// Abbrechen, wenn das beantragt wurde
if (isInterrupted())
{
// Alle ausstehenden Befehle löschen, damit isIdle()
// true zurückgibt
commands.clear();
breakRequested = true;
break;
}
// Den ersten, sprich ältesten, Befehl ausführen
exec(commands.get(0));
// Den ausgeführten Befehl löschen
commands.remove(0);
}
if (breakRequested)
break;
}
/*
* Das try/catch im try/catch ist deshalb da, damit ein
* Interrupt nicht gleich den Thread "gewaltsam" abbricht.
*/
try
{
// Eine halbe Sekunde lang warten...
Thread.sleep(500);
}
catch (final InterruptedException interrupt)
{
// Interrupt-Flag muss nach der Exception neu gesetzt werden
interrupt();
}
// ... und wieder prüfen
}
System.out.println("CommandDispatcher interrupted");
}
catch (final Exception e)
{
JOptionPane
.showMessageDialog(
null,
"Das Befehls-Abarbeitungssystem hat einen Fehler festgestellt\r\n"
+ "und musste beendet werden. Die Verbindung zum NXT wird jetzt getrennt.",
"Kritischer Absturz", JOptionPane.ERROR_MESSAGE);
}
}
/**
* Führt den übergebenen Befehl aus.
*
* @param command
* Ein Kommando-Objekt, das die Steuerdaten enthält
*/
private void exec(Command command)
{
System.out.println("exec command");
// TODO Hier müssen die Befehle rein
if (command.getCommand().equals("playSound"))
Sound.playTone(command.getParam(0), command.getParam(1));
// Zähler für ausgeführte Kommandos hochzählen
commandCount++;
}
/**
* Fügt Kommandos in die Warteliste ein.
*
* @param command
* Ein Kommando-Objekt, das in die Warteliste eingefügt werden
* soll
* @return true, wenn das Hinzufügen erfolgreich war, sonst false
*/
public boolean addCommand(Command command)
{
// Kommando an die Warteschlange anfügen
if (ignoreNew)
return false;
commands.add(command);
System.out.println("command added.");
return true;
}
/**
* Wird beim Beenden des Threads aufgerufen, damit noch alle Kommandos
* abgearbeitet werden können, bevor der Thread mit interrupt() beendet
* wird.
*
* @param option
* Ob neue Kommandos ignoriert werden sollen
*/
public void setIgnoreNew(boolean option)
{
ignoreNew = option;
}
/**
* Prüft, ob der Thread gerade beschäftigt ist oder nicht.
*
* @return true, wenn die Warteliste leer ist, d.h. der Thread nichts
* "zu tun" hat
*/
public boolean isIdle()
{
// Prüfen, ob die Kommandoliste leer ist
if (commands.size() == 0)
return true;
return false;
}
/**
* Gibt die Anzahl an Kommandos in der Warteliste zurück
*
* @return Die Anzahl an Kommandos in der Warteliste
*/
public int getCommandCount()
{
System.out.println("getting command count (" + commandCount + ")");
return commandCount;
}
}
FindBugs habe ich übrigens schon drüber laufen lassen, der findet zwar was, aber nichts zu diesem Problem, außer "Write to static field ui.Remote.commandDispatcherv2Class from instance method new ui.Remote()". Aber das hat doch eigentlich nur mit der Initialisierung zu tun, oder?