Java Thread [blockingqueue] hängt sich auf

Lord_Aratorn

Aktives Mitglied
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.
Java:
//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();
			}

Java:
//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;
	}
 
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...
 
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.

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.
 
Zuletzt bearbeitet:
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
Code:
packet = lnS.getReceivedmessage();
richtig deute...., was auch immer lnS ist.
 
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?
 
Zuletzt bearbeitet:
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.
 
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.
 
Um mehr Verständnis zu erzeugen, poste ich mal den wichtigen Teil des LNS:

Java:
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
 
Zuletzt bearbeitet:
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.
 
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.
 

Zurück
Oben