# Java Thread [blockingqueue] hängt sich auf



## Lord_Aratorn (29. Jan 2010)

Hi, Ich habe 2 verschiedene Threads, der eine empfängt UDP-Packete vom Netzwerk und soll sie in seine interne Queue schreiben.
Der Andere soll aus dieser Queue lesen und anschließend das erhaltene Packet weiter behandeln. Jedoch zerschießt sich Thread1, wenn eine Methode auf der Referenz des erhaltenen Packets ausgeführt wird.
Ich habe den etsprechenden Code unten gepostet.

In einem weiteren Ausschnitt des gesammten Projektes gibt es einem anderen Thread der genauso arbeitet wie Thread1. Dieser funktioniert jedoch tadellos. Ich vermute daher ein Problem mit der Threadinteraktion.

Danke für Eure Hilfe.

```
//Thread1
DatagramPacket packet = null;
while (true) {
			try {
				packet = lnS.getReceivedmessage();
				System.err.println("testausgabe 1");// wird noch ausgegeben
				System.out.println("packetdata:"+packet.getData());// hier hängt er sich weg
				
				InetAddress senderAddress = packet.getAddress();
				bmP.deserialize(packet.getData());
				handleIncommingMessagetype(senderAddress, bmP);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
```


```
//Thread2
	private BlockingQueue<DatagramPacket> receivedMessages = new LinkedBlockingQueue<DatagramPacket>();
        /*** nimmt erhaltenes DatagramPacket aus der Blockingqueue***/
	public DatagramPacket getReceivedmessage() throws InterruptedException {
		this.packet =receivedMessages.take();
		if (verbose)
			System.out.println("LNS: packet entnommen");
		return this.packet;
	}
```


----------



## FArt (29. Jan 2010)

Was heißt "der Thread zerschießt sich".  Hilft ein  ThreadDump, damit du siehst wo ein Thread "hängt"? Auf jeden Fall hilft Logging!

Im Prinzip ist das ein Standard: Producer-Consumer Problem... Google hilft da weiter...


----------



## Lord_Aratorn (29. Jan 2010)

FArt hat gesagt.:


> Was heißt "der Thread zerschießt sich".  Hilft ein  ThreadDump, damit du siehst wo ein Thread "hängt"? Auf jeden Fall hilft Logging!


Ich habe geloggt, und dies auch schon am Anfang im Eröffnungspost geschildert.
Nur kann ich mir nicht erklären warum und darum schreibe ich hier im Forum.
Mich würde es wundern, wenn das Objekt, welches von der getReceivedMessage-Methode zurückgeliefert wird, nicht vollständig ist. Da die Queue aus der das Objekt entnommen wird eine LinkedBlockingQueue ist und somit threadsave sein sollte.



FArt hat gesagt.:


> Im Prinzip ist das ein Standard: Producer-Consumer Problem... Google hilft da weiter...


Würde ich bezweifeln, weil soweit ich weiß, Producer und Consumer nicht übers Netzwerk communizieren.


----------



## Gast2 (29. Jan 2010)

Lord_Aratorn hat gesagt.:


> Würde ich bezweifeln, weil soweit ich weiß, Producer und Consumer nicht übers Netzwerk communizieren.


das Problem hat mit Netzwerk nichts am Hut


----------



## miwoe (29. Jan 2010)

a) Ich sehe nicht, wo die Queue beschrieben wird.

b) Du hast immer noch nicht beschrieben, was für dich weghängen bedeutet, dass ist Gamer-Slang  Richtig wäre sowas wie Deadlock, Livelock, Exception

Mein Tipp: Log mehr. Aus den Codeschnipseln kann man nicht viel erkennen. Ich sehe zum Beispiel keine 2 Threads arbeiten, sondern nur einen Methodenaufruf vom oberen zum unteren Code-Schnipsel. Zumindest wenn ich 
	
	
	
	





```
packet = lnS.getReceivedmessage();
```
 richtig deute...., was auch immer lnS ist.


----------



## Murray (30. Jan 2010)

Bedeutet "weghängen", dass die entsprechende Ausgabe, die aus dieser Codezeile resultieren sollte,  nicht mehr in der Konsole erscheint? Hast Du den Code schon mal im Debugger laufen lassen?


----------



## Lord_Aratorn (30. Jan 2010)

Murray hat gesagt.:


> Bedeutet "weghängen", dass die entsprechende Ausgabe, die aus dieser Codezeit resultieren sollte,  nicht mehr in der Konsole erscheint? Hat Du den Code schon mal im Debugger laufen lassen?



Genau, das bedeutet, dass die 2te Ausgabe nicht stattfindet. 
Ja, ich habe debuggt. Nur kann ich nicht ersehen wo der Fehler ist. Der Step into "sysout" endet direkt in einer "source not found exception", die von systemout stammt, da die binaries nur vorhanden sind. Wo wir übrigens bei Exception sind. Es wird keine Exception geworfen. Dies macht mich zudem sehr stutzig.

lns (unten beschrieben) ist wohl der Name der Referenz, des Threads, welcher die Methode getReceivedMessage() beinhaltet (die ich im übrigen ja auch gepostet habe), welche wohl die LinkedBlockingQueue nutzt um daraus "DatagramPackets" zu lesen.

@miwoe 
1) Schau nochmal genau hin! Sie ist im 2ten Codeschnipsel (der kommentiert wurde gleich an Anfang referenziert und instanziert worden).
2) Du hast wahrscheinlich recht, dass zu sehr informatiker-slang ist. Aber ich weiß halt nichtmal ob es überhaupt ein Lock ist, da alle Threads ohne Exception weiterarbeiten. Ich jedoch nicht an die übermittelten Informationen in dem DatagrammPacket komme. 
ps) Ich habe in den Kommentaren gesagt, dass ich 2 Threads habe, dies sollte reichen. Ich habe die Claas, in der Codeschnipsel 1 enthalten ist, von Thread abgeleitet. Genauso, wie die Class aus der Codeschnipsel 2 stammt (lns = LeafNodeServer) womit auch beantwortet ist, dass es der Thread ist, der auf den Netzwerk horcht.


Zu viel Code kann ich nicht veröffendlichen, da der Code Teil eines Projektes ist.


----------



## miwoe (1. Feb 2010)

Wie auch immer. Ich glaube nicht, dass das Problem die BlockingQueue ist. Eher hat es was mit der Übertragung zu tun. Was ist, wenn du versuchst die Daten des DatagramPacket von dem Thread zu loggen, der es in die Queue schreibt? Das wäre so dass, was ich als nächstes überprüfen würde.


----------



## Lord_Aratorn (1. Feb 2010)

Hey, guter Tip. Ich werde es mal versuchen und euch anschließend hier auf dem Laufenden Halten.


----------



## Lord_Aratorn (3. Feb 2010)

Um mehr Verständnis zu erzeugen, poste ich mal den wichtigen Teil des LNS:


```
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class LeafNodeServer extends Thread {
	private final int packetSize = 256;
	
	private static LeafNodeServer instance = null;

	private int port = 0;
	
	private DatagramPacket packet = null;
	private DatagramSocket socket = null;
	private BlockingQueue<DatagramPacket> receivedMessages = null;
		
	private boolean verbose = false;


	public static LeafNodeServer getLeafNodeServer(int port) {
		if (instance == null) {
			instance = new RootNodeServer(port);
		}
		return instance;
	}

	private LeafNodeServer(int port) {
		this.port = port;
		this.receivedMessages = new LinkedBlockingQueue<DatagramPacket>();
		this.packet = new DatagramPacket(new byte[packetSize],packetSize);
		try {
			this.socket = new DatagramSocket(this.port);
		} catch (SocketException e) {
			System.err.print("LeafNodeServer.constructor");
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		super.run();
		while(true){
			try {
				this.socket.receive(packet);
				this.receivedMessages.put(packet);
				if (verbose){
					System.out.println("LNS: received packet content: "+new String(packet.getData()));
					}
//				this.join();
			} catch (Exception e) {
				System.err.print("LeafNodeServer.run");
				e.printStackTrace();
			}
		}

	}

	public DatagramPacket getReceivedmessage() throws InterruptedException {
		DatagramPacket p = receivedMessages.take();
		System.out.println("LNS: take " + new String(p.getData()));
		return p;
	}
	
	public synchronized void verbose() {
		this.verbose = true;
	}
}
[/Java]

Ich habe das Problem bis in Zeile 62 eingrenzen können (auch hier wird die Ausgabe nicht durchgeführt). Es scheint so, als wäre das Objekt, welches aus der Queue entnommen wird deffekt. 
In der Queue scheint ein Packet enthalten zu sein, zumindest wird die Ausgabe in Zeile 49 erfolgreich ausgeführt, wenn ein Paket erhalten wurde.

[code]
[toString() unavailable - no suspended threads]
```
ist nach ausführen der Ausgabe in Zeile 62 im DatagramPacket (packet) der Wert in allen Variablen des Packets


----------



## Lord_Aratorn (3. Feb 2010)

Ok, ich habe den Fehler gefunden.

Das Problem lag darin, dass für jedes empfangene Paket das selbe DatagramPacket-Objekt genutzt wurde.
Ich weiß zwar nicht, warum dadurch ein Problem entsteht. Ich vermute mal, dass wenn ein Packet den Server erreicht, bevor ein Anderes verarbeitet wurde, das alte Objekt zerstört wird.


----------



## FArt (3. Feb 2010)

> Ich vermute mal, dass wenn ein Packet den Server erreicht, bevor ein Anderes verarbeitet wurde, das alte Objekt zerstört wird.


Das liegt aber an der eigenen Implementierung, oder?


----------



## Lord_Aratorn (3. Feb 2010)

FArt hat gesagt.:


> Das liegt aber an der eigenen Implementierung, oder?


Hm keine Ahnung was letztendlich der Grund ist.

Also Zeile 32 zwischen 44 und 45 und es läuft einwandfrei


----------



## Empire Phoenix (3. Feb 2010)

this.socket.receive(packet);
                this.receivedMessages.put(packet);

simple ein Datagrampacket hat im kern ein bytearray als speicher, arrays sind in java nicht primitiv, dh call by reference -> wenn du die daten änderst werden alle referenzen die die daten verwended ad absurdum geführt.


----------

