Hallo zusammen,
ich arbeite aktuell an einem Programm, welches die serielle Schnittstelle nutzt. Soweit so gut, RXTX funktioniert auch.
Nun kommt aber dazu, dass ich mehrere Threads habe.
Prozess 1 schreibt auf die serielle Schnittstelle,
Prozess 2 liest azf der seriellen Schnittstelle und
Prozess 3 ist das Programm selber, welches auch die Daten verarbeitet.
Dazu habe ich 2 Listen generiert, die als Puffer fungieren. Beide befinden sich in Prozess 3. Dazu gibt es entsprechende Methoden, um auf besagte Listen zugreifen. Das ganze sieht dann so aus:
Prozess 1 - gekürzt
Prozess 2 - gekürzt
Prozess 3 - relevante Teile
Meine Frage ist nun, habe ich dies mit dem synchronized bei den Methoden richtig gemacht?
Muss ich die Methoden synchronisieren oder muss ich das ganze eventuell ganz anders machen.
Ich muss zugeben, so 100% blicke ich das noch nicht.
Was ich halt verhindern will ist, dass eine Nachricht eventuell nur halb in einen ansonsten leeren Puffer geschoben wird und dann eine Auswertung erfolg und alles irgendwie vor die Wand läuft.
Also habe ich mir gedacht, in Prozess 3 muss ich die Zugriffsmethoden auf die Liste, egal von welcher Seite synchronisieren, oder?
Außerdem möchte ich natürlich die Prozesse 1 und 2 sauber beenden, wenn die Serielle Schnittstelle nicht mehr benötigt wird. Ob nach beenden Aufforderung bis zum wirklichen beenden noch etwas in den Puffer geschrieben wird ist dabei egal, da dies nicht mehr verarbeitet wird und etwas später sowieso verworfen wird.
Ich hoffe Ihr könnt mir sagen, ob das so passt oder eher vollkommener Blödsinn ist.
ich arbeite aktuell an einem Programm, welches die serielle Schnittstelle nutzt. Soweit so gut, RXTX funktioniert auch.
Nun kommt aber dazu, dass ich mehrere Threads habe.
Prozess 1 schreibt auf die serielle Schnittstelle,
Prozess 2 liest azf der seriellen Schnittstelle und
Prozess 3 ist das Programm selber, welches auch die Daten verarbeitet.
Dazu habe ich 2 Listen generiert, die als Puffer fungieren. Beide befinden sich in Prozess 3. Dazu gibt es entsprechende Methoden, um auf besagte Listen zugreifen. Das ganze sieht dann so aus:
Prozess 1 - gekürzt
Java:
final class SerialWriter
extends Thread
{
private OutputStream stream;
private Serial serial;
private boolean run;
protected SerialWriter(Serial serial, OutputStream stream)
{
this.stream = stream;
this.serial = serial;
run = true;
}
protected final void exit() // Hierüber wird von Prozess 3 aus dieser Prozess beendet
{
run = false;
}
public final void run ()
{
Nachricht message;
while(run == true)
{
message = serial.getSendMessage(); // Hier wird die Nachricht aus Prozess 3 geholt.
if(message == null)
{
try
{
sleep(200);
}
catch(InterruptedException e)
{
//Nix tun
}
}
else
{
try
{
stream.write(message.getID());
[...]
}
catch(IOException e)
{
serial.sendefehler(); // Hier wird ein eventueller Fehler an Prozess weiter gereicht
}
}
}
}
}
Prozess 2 - gekürzt
Java:
final class SerialReader
extends Thread
{
private InputStream stream;
private Serial serial;
private boolean run;
protected SerialReader(Serial serial, InputStream stream)
{
this.stream = stream;
this.serial = serial;
run = true;
}
protected final void exit() // Hierüber wird von Prozess 3 aus dieser Prozess beendet
{
run = false;
}
public final void run ()
{
int wert;
boolean gewartet;
while(run == true)
{
gewartet = false;
try
{
wert = stream.read();
}
catch(IOException e)
{
serial.empfangfehler();
wert = -1;
}
if(wert == -1)
{
try
{
sleep(100);
}
catch(InterruptedException e)
{
//Nix tun
}
}
else
{
EmpfangsNachricht message = new EmpfangsNachricht();
try
{
message.setzeID(wert);
wert = stream.read();
if(wert == -1 && gewartet == false)
{
try
{
sleep(100);
}
catch(InterruptedException e)
{
//Nix tun
}
gewartet = true;
wert = stream.read();
}
if(wert == -1)
{
message.setzeStatus(false);
serial.setReceiveMessage(message);
continue;
}
message.setzeDLC(wert);
[...]
serial.setReceiveMessage(message); // Hier wird die nachricht an Prozess 3 weiter gereicht
}
catch(IOException e)
{
serial.empfangfehler(); // Hier wird ein eventueller Fehler an Prozess weiter gereicht
}
}
}
}
}
Prozess 3 - relevante Teile
Java:
public final class Serial
{
private LinkedList<Nachricht> sendepuffer;
private LinkedList<EmpfangsNachricht> empfangspuffer;
private SerialReader reader;
private SerialWriter writer;
public Serial()
{
sendepuffer = new LinkedList<Nachricht>();
empfangspuffer = new LinkedList<EmpfangsNachricht>();
}
public final boolean open(String port, int baud)
{
[ ... ]
InputStream in;
OutputStream out;
try
{
in = serialPort.getInputStream();
out = serialPort.getOutputStream();
}
catch(IOException e)
{
serialPort.close();
return false;
}
reader = new SerialReader(this, in);
reader.start();
writer = new SerialWriter (this, out);
writer.start();
geoeffnet = true;
return true;
}
public synchronized final boolean close()
{
if(geoeffnet == false)
return true;
reader.exit();
writer.exit();
serialPort.close();
geoeffnet = false;
return true;
}
public synchronized final boolean transmit(Nachricht message)
{
sendepuffer.add(message);
return true;
}
public synchronized final EmpfangsNachricht receive()
{
EmpfangsNachricht message = empfangspuffer.remove();
return message;
}
protected synchronized final Nachricht getSendMessage()
{
Nachricht message = sendepuffer.remove();
return message;
}
protected synchronized final void setReceiveMessage(EmpfangsNachricht message)
{
empfangspuffer.add(message);
}
protected synchronized final void empfangfehler()
{
fehler = true;
}
protected synchronized final void sendefehler()
{
fehler = true;
}
}
Meine Frage ist nun, habe ich dies mit dem synchronized bei den Methoden richtig gemacht?
Muss ich die Methoden synchronisieren oder muss ich das ganze eventuell ganz anders machen.
Ich muss zugeben, so 100% blicke ich das noch nicht.
Was ich halt verhindern will ist, dass eine Nachricht eventuell nur halb in einen ansonsten leeren Puffer geschoben wird und dann eine Auswertung erfolg und alles irgendwie vor die Wand läuft.
Also habe ich mir gedacht, in Prozess 3 muss ich die Zugriffsmethoden auf die Liste, egal von welcher Seite synchronisieren, oder?
Außerdem möchte ich natürlich die Prozesse 1 und 2 sauber beenden, wenn die Serielle Schnittstelle nicht mehr benötigt wird. Ob nach beenden Aufforderung bis zum wirklichen beenden noch etwas in den Puffer geschrieben wird ist dabei egal, da dies nicht mehr verarbeitet wird und etwas später sowieso verworfen wird.
Ich hoffe Ihr könnt mir sagen, ob das so passt oder eher vollkommener Blödsinn ist.