Threads Synchronisieren

TDO88

Bekanntes Mitglied
Hallo Zusammen,

ich habe eine Anwendung, die mit mehreren Threads läuft.
Es gibt die Klasse Video, welche einen Thread enthält, der dauerhaft Bilder einer angeschlossenen Kamera auswertet und eine Hauptklasse, in welcher es einen Thread gibt, der mehrere Messungen ausführt.
Der KameraThread wertet die Bilder aus stellt einige Messwerte zur Verfügung, für die es getFunktionen in der Video Klasse gibt.
Aus dem Messungsthread hole ich mir dann zu bestimmten Zeitpunkten Messergebnisse aus den getFunktionen.
Ich habe es mit Conditions -> SignalAll() und await() probiert.

Hier ein vereinfachter Code des ganzen:
Java:
public class Video extends javax.swing.JFrame
{
     private final Lock lock = new ReentrantLock();
    public final Condition FrameReady = lock.newCondition();
     class VideoThread implements Runnable
    {
         
          @Override
                public void run() {
                        //Hier werden die Kameradaten verarbeitet
                        FrameReady.signalAll();
                }
    }

     public synchronized Point getPosition() {
        if (myThread != null)
        {
            lock.lock();
            try{
                synchronized(FrameReady)
                {
                    FrameReady.await();
                }
            }catch(InterruptedException ex)
            {
                JOptionPane.showMessageDialog(null, "Interrupted Exception in Vido.getPosition!\nFehler: " + ex.getMessage(), "Interrupted Exception", JOptionPane.ERROR_MESSAGE);
            }
                finally{
                lock.unlock();
            }
            return myThread.measuredResult;
        }
        else return new Point(0,0);
    }
   
public synchronized double getPosX() {
        if (myThread != null)
        {
            lock.lock();
            try{
                synchronized(FrameReady)
                {
                    FrameReady.await();
                }
            }catch(InterruptedException ex)
            {
                JOptionPane.showMessageDialog(null, "Interrupted Exception in Vido.getPosX!\nFehler: " + ex.getMessage(), "Interrupted Exception", JOptionPane.ERROR_MESSAGE);
            }
                finally{
                lock.unlock();
            }
            return myThread.XX;
        }
        else return 0.0;
    }
}

Im MessThread möchte ich dann über die getFunktionen die benötigten Werte bekommen, aber vom aktuellen Bild. Ich habe nämlich aktuell ohne signalAll() und await() manchmal das Problem, dass ich die Messergebnisse eines älteren Bildes bekomme.
Ich bekomme bei signalAll() eine IllegalMonitorStateException.
Kann mir jemand erklären, warum das so ist und was ich verbessern muss?
Kann ich aus dem MessungsThread auf das Condition Objekt zugreifen und in dem Thread auf ein signalAll des VideoThreads warten?!

Gruß
TDO
 
Ich habe jetzt spaßeshalber mal signalAll() mit notifyAll() und await() mit wait() ersetzt.
Jetzt bekomme ich zumindest keine Exception mehr und es scheint zu funktionieren. Worin liegt denn der Unterschied und ist es prinzipiell vom Aufbau so richtig oder ist da im generellen Aufbau etwas verbesserungswürdig?
 
Ich würde da eher eine BlockingQueue benutzen, der VideoThread fügt seine Ergebnisse einfach hinzu, der andere fragt sie daraus ab.

Ein Getter in Verbindung mit asynchronen aufrufen finde ich zumindest etwas merkwürdig...

Ich bekomme bei signalAll() eine IllegalMonitorStateException.
Kann mir jemand erklären, warum das so ist und was ich verbessern muss?
Das signalAll muss auch über FrameReady synchronized sein.
 
Ich verstehe ehrlich gesagt nicht warum du die thread überhaupt snchronisieren willst. Wenn der Messergebnisse Thread die Daten beim Video Thread abholt bekommt er immer die Werte des letzten ausgelesenen Bildes. Wenn das nicht das aktuelle ist, dann ist das aktuelle halt noch nicht fertig ausgewertet und damit auch nicht das aktuell zur Verfügung stehende. Es stehen also nur die Messwerte des Bildes davor zur Verfügung was doch vollkommen in Ordnung ist.
Ansonten bringt es ja gar nichts das in verchiedenen Threads zu machen wenn der Messergebnisse Thread eh immer auf das Bild warten muss das gerade ausgewertet wird. Dann kannst du die auch synchrobn nacheinander laufen lassen.

Gruß

Claus
 
Danke für die Antwort.
Es wird die ganze Zeit auch ein Live-Bild auf einem JFrame angezeigt. Über das Live-Bild werden dann noch Messlinien usw. gezeichnet. Deshalb läuft das über die parallelen Threads.
Wenn das nicht das aktuelle ist, dann ist das aktuelle halt noch nicht fertig ausgewertet und damit auch nicht das aktuell zur Verfügung stehende. Es stehen also nur die Messwerte des Bildes davor zur Verfügung was doch vollkommen in Ordnung ist.

Eben nicht, wenn sich im Bild etwas bewegt und du es zu einem bestimmten Zeitpunkt haben möchtest, kann es eben nicht okay sein, das vorherige Bild zu bekommen. Dann warte ich lieber noch ein paar ms und habe dann wirklich ein aktuelles Bild. Vor der Kamera wird etwas bewegt -> angehalten -> Bild auswerten -> weiter bewegen.
Die Kamera hat eine relativ hohe Auflösung und somit schafft das System leider nur ca. 5 FPS. Da kann es sein, dass ein zu altes Bild Fehler in der Messung ergibt.

Nochmal die Frage, warum es mit notify() funktioniert und mit signal() nicht?!

Gruß
TDO
 
Oh sorry, hatte deine erste Antwort leider übersehen.
Ich hatte es auch mal versucht signalAll über FrameReady zu synchronisieren, hatte aber leider auch nicht geklappt.
Worin liegt denn der Unterschied zwischen signal() und notify()? Für mich sehen beide Methoden gleich aus?!
Bei einer BlockingQueue wäre ein Live-Bild nicht möglich oder? Da würden doch dann nur Bilder von der Kamera abgeholt, wenn ich einen Messwert brauche oder?

Gruß
TDO
 

Neue Themen


Zurück
Oben