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
1
staticclassprintOutimplementsRunnable
2
{
3
ArrayBlockingQueue<byte[]>queue;
4
5
printOut(){
6
queue=newArrayBlockingQueue<byte[]>(100,true);
7
}
8
9
publicvoidrun()
10
{
11
byte[]rec=null;
12
while(true)
13
{
14
try{rec=queue.poll(1,TimeUnit.MINUTES);}
15
catch(InterruptedExceptionexc){}
16
if(null==rec)
17
{
18
System.out.println("Timeout");
19
continue;
20
}
21
System.out.println...
22
}
23
}
24
publicvoidpush(byte[]val)
25
{
26
queue.add(val);
27
}
28
}
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
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...
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.
1
importpeak.can.basic.TPCANMsg;
2
TPCANMsgmsg=newTPCANMsg();
3
while(true)
4
{
5
res=pcan.Read(hnd,msg,null);
6
if(TPCANStatus.PCAN_ERROR_OK==res)
7
{
8
//Versenden an Lan
9
//System.println
10
}
11
}
> 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.
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.
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 :-)
>> 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.
1
while(true)
2
{
3
try{rec=queue.poll(1,TimeUnit.MINUTES);}
4
catch(InterruptedExceptionexc){}
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.
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
1
inta=5;
2
if(a=6){
3
//Uppppsss...
4
}
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.
> 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.
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...
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.