www.mikrocontroller.net

Forum: PC-Programmierung Java Thread Messaging


Autor: J.W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe ein Java Programm, wo ich von einem Can-Adapter Daten empfange, 
die ich mit wenigst Zeitverzug auf LAN/Udp weiterreiche.
Das funktioniert sehr gut.

Parallel moechte ich die Daten per System.out.println auf der Konsole 
sehen, und das bremst meine Bridge aus.
Wenn ich das Konsolen-Window verschiebe, dan haengt die Bridge total.

Deshalb mache ich die println-Ausgaben in einem extra Thread
static class printOut implements Runnable
{
ArrayBlockingQueue<byte[]> queue;

printOut() {
  queue=new ArrayBlockingQueue<byte[]>(100,true);
}

public void run()
{
  byte[] rec=null;
  while (true)
  {
    try {rec=queue.poll(1,TimeUnit.MINUTES);}
    catch (InterruptedException exc) {}
    if (null==rec)
    {
      System.out.println("Timeout");
      continue;
    }
    System.out.println ...
  }
}
public void push(byte[] val)
{
  queue.add(val);
}
}


Woanders wandle ich die CAN-Daten in ein Byte Array und schiebe dieses 
Array in die obige Queue.

Das Funktioniert zwar, aber es gefaellt mir nicht:
Bei jeder Message wird ein byte[]-Array angelegt.
Irgendwann ist der Speicher voll, und dann bremst der Garbage-Kollektor 
das System.
Ich muss dazu sagen, dass ich bei Java bei zeitkritischen Programmen 
dynamische Speicherbelegungen vermeide, d.h. ich lege die Objekte bei 
Programmstart an und erzeuge dann moeglichst wenig neue.

Wie koennte ich mein Problem anders/besser loesen, d.h. 
System.out.println() Ausgaben, die das System nicht ausbremsen?

Gruss, Juergen

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
J.W. schrieb:
> Parallel moechte ich die Daten per System.out.println auf der Konsole
> sehen, und das bremst meine Bridge aus.
Kann es sein das dein Thread suspended wird in der Zeit?
Du könntest auch mal versuchen das ganze in einen BufferedWriter zu 
wrappen, vieleicht hilft es.

J.W. schrieb:
> Bei jeder Message wird ein byte[]-Array angelegt.
Versteh ich nicht, die Daten müssen doch irgenwo herkommen, also muß das 
byte Array doch so oder so angelegt werden...

Mit Messagin hat das übrigens nix zu tun, du wartest ja nicht auf eine 
Benachrichtigung von einem anderen Thread.

J.W. schrieb:
> Irgendwann ist der Speicher voll, und dann bremst der
> Garbage-Kollektor das System.
Denkst du oder weißt du? Was ist den das für ein System wo alles den 
Bach runtergeht wenn du ne Simple Konsolenausgabe machst und etwas GC...

Autor: J.W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi .. schrieb:
> J.W. schrieb:
>> Bei jeder Message wird ein byte[]-Array angelegt.
> Versteh ich nicht, die Daten müssen doch irgenwo herkommen, also muß das
> byte Array doch so oder so angelegt werden...
>

Ohne Extra-Thread legte ich die Daten-Struktur nur einmal an.
Es wurde ja nur eine gebraucht.
import peak.can.basic.TPCANMsg;
TPCANMsg msg=new TPCANMsg();
  while (true)
  {
    res=pcan.Read(hnd,msg, null);
    if (TPCANStatus.PCAN_ERROR_OK==res)
    {
      //Versenden an Lan
      //System.println
    }
  }

> Mit Messagin hat das übrigens nix zu tun, du wartest ja nicht auf eine
> Benachrichtigung von einem anderen Thread.

Naja, ich dachte, ich muss einem Thread eine Nachricht schicken, dass er 
was ausgibt.
Dabei hatte ich die Windows-Routine PostThreadMessage im Kopf.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann übergib die Datenstruktur doch an deine anderen Thread wozu noch 
ein extra Bytearray?

J.W. schrieb:
> Dabei hatte ich die Windows-Routine PostThreadMessage im Kopf.
ThreadMessagin ist eher sowas wie wait und notify, aber egal, tut ja 
hier nix zur Sache.

> if (TPCANStatus.PCAN_ERROR_OK==res)
Schreib es lieber so
> if (res == TPCANStatus.PCAN_ERROR_OK)
Die umgekehrte Schreibweise verwirrt nur.

Autor: J.W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi .. schrieb:
> Dann übergib die Datenstruktur doch an deine anderen Thread wozu noch
> ein extra Bytearray?

Geht das?
Arrays und Objekte werden bei java nur als Referenz uebergeben.
Wenn ich in die Queue 20x mal die gleiche Referenz reinschreibe, dann 
holt er immer die aktuellen Werte von diesem Array.
Wobei ich eher annehme, dass das Array in queue.add() kopiert wird und 
neuer Speicher angelegt wird.
Anders waere es, wenn ich int oder long werte in der Queue habe.
Aber ArrayBlockingQueue<E> verlangt Objekte.


>
> J.W. schrieb:
>> Dabei hatte ich die Windows-Routine PostThreadMessage im Kopf.
> ThreadMessagin ist eher sowas wie wait und notify, aber egal, tut ja
> hier nix zur Sache.
>
>> if (TPCANStatus.PCAN_ERROR_OK==res)
> Schreib es lieber so
>> if (res == TPCANStatus.PCAN_ERROR_OK)
> Die umgekehrte Schreibweise verwirrt nur.

Und wenn ich unabsichtlich statt '==' nur '=' schreibe? Das sieht man 
nicht sofort und an solchen Fehlern kann man Stunden/Tage suchen.
Ich spreche aus Erfahrungen.
Irgendwo habe ich gelesen, dass man bei Vergleichen (==) an der linken 
Seite nur Operanden schreibt, die der Compiler nicht als L-Value 
interpretieren kann.
Seitdem habe ich nie mehr = und == verwechselt :-)

Autor: J.W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>
> J.W. schrieb:
>> Dabei hatte ich die Windows-Routine PostThreadMessage im Kopf.
> ThreadMessagin ist eher sowas wie wait und notify, aber egal, tut ja
> hier nix zur Sache.
>

Ich denke, das laeuft bei der Queue im Hintergrund ab.
  while (true)
  {
    try {rec=queue.poll(1,TimeUnit.MINUTES);}
    catch (InterruptedException exc) {}
Hier bleibt der Thread stehen, bis in der Queue was drinsteht.
D.h. wait und notify
Auch muss die Queue gegenseitig mit Semaphoren gesperrt werden.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
J.W. schrieb:
> Geht das?
Ja warum den nicht?
> Wenn ich in die Queue 20x mal die gleiche Referenz reinschreibe, dann
> holt er immer die aktuellen Werte von diesem Array.
??? Dann hat die Queue halt 20 gleiche Einträge sollte ihn nicht stören 
;)

> Wobei ich eher annehme, dass das Array in queue.add() kopiert wird und
> neuer Speicher angelegt wird.
Diese Annahme würde ich einfach mal ohne Gegenbeweis als nicht 
zutreffend bezeichnen. Wenn du es nicht explizit anforderst wird in Java 
garnix kopiert.

> Anders waere es, wenn ich int oder long werte in der Queue habe.
> Aber ArrayBlockingQueue<E> verlangt Objekte.
ArrayBlockingQueue<Long> nehemen...

> Und wenn ich unabsichtlich statt '==' nur '=' schreibe? Das sieht man
> nicht sofort und an solchen Fehlern kann man Stunden/Tage suchen.
> Ich spreche aus Erfahrungen.
Dann hast du deine Erfahrung aus anderen Sprache, in Java ist
int a = 5;
if (a = 6) {
  //Uppppsss...
}
Kein gültiger Code und wird vom Compiler zurückgewiesen: Type mismatch: 
cannot convert from int to boolean.

> Irgendwo habe ich gelesen, dass man bei Vergleichen (==) an der linken
> Seite nur Operanden schreibt, die der Compiler nicht als L-Value
s.o. tut er so auch nicht, es gib in Java nur einen Fall wo das so sein 
kann und das ist bei boolean Werten, diese vergleicht man aber eh nicht 
auf true/false in einer Bedingung.

Autor: J.W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Anders waere es, wenn ich int oder long werte in der Queue habe.
> Aber ArrayBlockingQueue<E> verlangt Objekte.
ArrayBlockingQueue<Long> nehemen...

Mmm, das ist auch wieder ein Objekt, wo der Inhalt dynamisch allokiert 
wird.

>> nicht sofort und an solchen Fehlern kann man Stunden/Tage suchen.
>> Ich spreche aus Erfahrungen.
>Dann hast du deine Erfahrung aus anderen Sprache, in Java ist

Richtig. Die Erfahrung war nicht in Java. Aber man gewoehnt sich 
Schreibweisen an.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
J.W. schrieb:
>> Anders waere es, wenn ich int oder long werte in der Queue habe.
>> Aber ArrayBlockingQueue<E> verlangt Objekte.
> ArrayBlockingQueue<Long> nehemen...
> Mmm, das ist auch wieder ein Objekt, wo der Inhalt dynamisch allokiert
> wird.
Ja nun, irgenwo muß der Speicher für deine Zahl ja her kommen, wo ist 
das Problem? Ich würde da nicht so ängstlich sein, ggf "übersetzt" der 
schlaue Compiler/JVM das sogar in equivalenten Code...

> Richtig. Die Erfahrung war nicht in Java. Aber man gewoehnt sich
> Schreibweisen an.
Für Java würde ich es mir abgewöhnen, es ist einfach unüblich und macht 
den Code schwer lesbar...

Autor: PI314 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das Verschicken vom Ausdrucken einfach entkoppeln...
ExecutorService sendService = Executors.newSingleThreadExecutor();
ExecutorService printService = Executors.newSingleThreadExecutor();

while(true){
  MyRecord rec = queue.poll();
  if(rec != null){
    //queue is not empty
    sendService.submit(new ElementarSender(rec));
    printService.submit(new ElementarPrinter(rec));
  } else {
    //queue is empty
    //sleep...
  }
}
Will man mehr Kontrolle behalten, steigt man auf peek() um und übergibt 
den Record sammt zwei Future dem dritten Service, der sich nach einer 
bestimmten Strategie ums "Bereinigen" kümmert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.