Micha: COMM-API - Sinn des Thread und Variablenüberwachung

Hallo,

ich habe zwei Fragen, die auf der COMM-API aufbauen.

Im Beipsiel der COMM-API SimpleRead.java wird ein Thread gestartet. In der Beschreibung steht, das dieser einen asynchronen Lesevorgang ermöglicht (das fällt bei diesem Beispiel doch gar nicht ins Gewicht oder?). Nur, welchen nutzen hat es, diesen 20 sec zu unterbrochen, bevor er loslegt oder mißverstehe ich das sleep(20000)?

Meine zweite Frage ist, wie kann ich den Status einer Variable in einer anderen Klasse überwachen - bzw. wie geht man hier vor?
Wenn ich von der Schnittstelle etwas zurückbekomme, könnte ich ja bspw. einen boolischen Wert von false auf true setzen.

Wenn ich den Wert nun in einer anderen Klasse direkt abfrage, ist er jedoch noch false, da die Antwort noch nicht gesendet bzw. noch unvollständig ist. In einer while-Schleife laufend den Statuswert zu prüfen, erscheint mir auch stark fragwürdig. ;-)

Welche Möglichkeiten habe ich hier, gibts dafür eine Art Listener?

Mit freundlichem Gruß
Micha

  1. Hallo Micha!

    Zu 1: (die sleep 20000 sind nur da, um einen  lange andauernden Vorgang zu simulieren)
    Der Vorteil ist, dass du ja theoretisch mehrere solche Threads haben könntest und diese dann parallel ihre Arbeit erledigen können.
    Z.B.: Parallel zueinander eine grosse Datei über Modem empfangen und von der Tastatur weiterhin Programmeingaben annehmen (die ja nicht zu definierten Zeitpunkten kommen) und zugleich noch was anderes tun...

    zu 2:
    Also, ich kann dir zwar nicht die genaue Java Syntax sagen, aber im allgemeinen Fall (mit lange dauernden Operationen) könnten z.B. Semaphoren als Flags verwendet werden:

    main process -> create semaphore
    main_process -> start thread;
    main_process (sleep a little, to allow thread to get semaphore)
                                  thread (open & get semaphore)
    main_process (sem_wait)       thread (do timeintense operations)
                                  thread (set result)
                                  thread (sem_post)
    main_process (get result)
    main_process (destroy_semaphore)

    oder man verwendet signals:

    main_process (contains signal handler for e.g. SIG_USR1)
    main_process -> start thread;
    main_process (sleep);         thread (do timeintense operations)
                                  thread (set result)
                                  thread (SIG_USR1)
    main_process (awake form sleep due to signal)
    main_process (get result)

    Grüsse,
    Richard

    1. Hallo Richard,

      veilen Dank für Deine Antwort. Ich nenn mal meinen konkreten Fall. Ich möchte ein Instrument über die Schnittstelle ansprechen. Laut dem Handbuch, und meine ersten Versuche bestätigen das auch, sendet man immer eine Anfrage und bekommt dann eine Antwort. Erst wenn man die Antwort hat, kann man die nächste Anfrage stellen. Wenn ich Deine Erklärung richtig interpretiere:

      Zu 1: (die sleep 20000 sind nur da, um einen  lange andauernden Vorgang zu simulieren)
      Der Vorteil ist, dass du ja theoretisch mehrere solche Threads haben könntest und diese dann parallel ihre Arbeit erledigen können.

      Ist dies für mich überflüssig, da ich das Ereignis "Antwort" so oder so abwarten muss, bevor ich den nähsten Befehl absenden kann. Da erst die Antwort mögliche Aktionen hervorruft.

      Beim zweiten hole ich auch etwas aus: Ich habe mir ein Klasse aus dem SimpleRead/Write zusammengebastelt. Wie gesagt, die Komunikation funktioniert soweit auch. Ich sende eine Anfrage und auf der Konsole wird die Antwort ausgegeben. Sie kommt auch recht schnell - einstelliger Sekundenbereich (gefühlt); zeitkritsich ist eine Streckenessung mit einem Laser, die auch fehlschlagen kann. Aber ansonsten antwortet das Instrument recht fix.

      Also, ich kann dir zwar nicht die genaue Java Syntax sagen, aber im allgemeinen Fall (mit lange dauernden Operationen) könnten z.B. Semaphoren als Flags verwendet werden:

      Gut das werde ich mal ergooglen.

      Mit freundlichem Gruß
      Micha

    2. Hallo Richard,

      kann ich es auch innerhalb einer Klasse irgendwie erreichen, die while-Schleife zu umgehen?

      Ich habe es derzeit wie folgt (Auszug)

        
      public class SerialStream implements Runnable, SerialPortEventListener {  
        //.....  
        
        public void sendRequest(String messageString){  
          try {  
            this.hasSendRequest = true;  
            this.outputStream.write( messageString.getBytes() );  
            this.response = new String("");  
            this.hasResponse = false;  
            //this.readThread = new Thread(this);  
            //this.readThread.start();  
          } catch (IOException e) {  
            this.hasSendRequest = false;  
            System.err.println("Fehler "+e);  
          }  
        }  
        
        public String getResponse(){  
          while (this.hasSendRequest && !this.hasResponse){ /** do nothing... **/  }  
          this.hasSendRequest = false;  
          return this.response;  
        }  
        
        public void serialEvent(SerialPortEvent event) {  
          if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {  
            byte[] readBuffer = new byte[20];  
        
            try {  
              while (this.inputStream.available() > 0) {  
                int numBytes = this.inputStream.read(readBuffer);  
              }  
              String resStr = new String(readBuffer);  
              this.response += resStr.trim();  
              //System.out.println(new String(response));  
              if (resStr.indexOf("\n")!=-1){  
                //System.out.println(this.response);  
                this.hasResponse = !this.response.isEmpty();  
              }  
        
            } catch (IOException e) {  
              System.err.println("Fehler "+e);  
            }  
        
          }  
        }  
        
        //......  
      }  
      
      

      Wenn das Instrument antwortet, durchsuche ich den String nach einem Umbruch (\n), das ist das Zeichen, dass der Response vollständig ist.

      Nun setz ich die Variabel hasResponse auf true.

      Der Aufruf sieht nun wie folgt aus:

        
      serialStream.sendRequest( "Hallo Welt" );  
      serialStream.getResponse();
      

      Ich stelle als eine Anfrage und fage *sofort* nach der Antwort des Instrumentes. Da diese natürlich auf sich warten lässt, überbrück ich die Zeit in einer leeren while-Schleife:
      while (this.hasSendRequest && !this.hasResponse){ /** do nothing... **/ }

      Sowas lässt sich doch sicher schöner lösen, oder?

      Mit freundlichem Gruß
      Micha