Mehrere Threads - ein Stack

Flu

Mitglied
Hi Leute.
Ich bin noch nicht so firm in nebenläufiger Programmierung und stehte jetzt vor einem Problem.
Ein Programm besteht aus mehreren Threads.
In der Hauptklasse exisitert ein Stack, in dem jeder Thread Strings ablegen soll, damit die Hauptklasse diese auslesen kann.
Dafür wir den Nebenklassen die Hauptklasse übergeben - diese rufen dann per hauptklasse.commands.add(...) den Stack auf.

Dabei werden auch keine Exceptions geworfen - allerdings ist der Stack immer leer?!

Gibt es da eine möglichkeit? Alle Klassen sind von Thread abgeleitet.
 
klingt eher nach denkbaren Nebenproblemen wie doch nicht Hauptklasse übergeben sondern neu erstellt -> verschiedene Objekte,
manche leer, manche nicht

komplettes kleines Codebeispiel wäre hilfreich
 
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Stack;
import java.util.StringTokenizer;


public class Client extends Thread {

	// Verbindungsvariablen
	final String user = "user";
	final String pass = "pass";
	public String host = "localhost";
	int port = 21;
	
	
	// PASV
	int portNew;
	String ipNew = "";

	public Stack<String> commands = new Stack<String>();

	boolean lastCommand = false;

	// Sockets
	Socket serverSocket;
	Socket pasvSocket;
	PrintWriter writeCommands;
	BufferedReader fromServer;
	
	PrintWriter writePasvCommands;
	BufferedReader fromPasvServer;

	// Baut die Verbindung auf
	public void connect() throws IOException {

		try {
			serverSocket = new Socket(host, port);
			System.out.println("Baue Verbindung auf ...");
			fromServer = new BufferedReader(new InputStreamReader(
					serverSocket.getInputStream()));
			writeCommands = new PrintWriter(serverSocket.getOutputStream(),
					true);
		} catch (UnknownHostException e) {
			System.out.println("Host unbekannt!");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void USER() throws IOException {
		writeCommands.print("USER " + user + "\n");
		writeCommands.flush();
	}
	
	public void PASS() {
		writeCommands.print("PASS " + pass +"\n");
		writeCommands.flush();
	}
	
	public void NOOP() {
		writeCommands.print("NOOP\n");
		writeCommands.flush();
	}
	
	public void getStatus() {
		Thread konsole = new Thread(new Konsole(this));
		konsole.start();
	}
	
	// PASV anschalten
	public void PASV() throws IOException, InterruptedException {
		
		writeCommands.print("PASV\n");
		writeCommands.flush();
		getPasvCon();
		

	}
public synchronized void getPasvCon() throws IOException, InterruptedException {
		System.out.println("!!!!!!");
		// Commands abholen
		

		// IP Adresse holen

		String pasv = commands.lastElement(); 
		String ipAndPort = pasv.substring(pasv.indexOf("(") + 1,
				pasv.indexOf(")"));

		StringTokenizer getIp = new StringTokenizer(ipAndPort);

		// holt die IP
		String ipNew = "";   // IP für den neuen Socket
		for (int i = 0; i < 4; i++) {
			if (i < 3) {
				ipNew += (getIp.nextToken(",") + ".");
			} else {
				ipNew += (getIp.nextToken(","));

			}
		}


		Integer portTemp1 = new Integer( getIp.nextToken(","));
		Integer portTemp2 = new Integer (getIp.nextToken(","));
		portNew = (portTemp1 << 8 )+ portTemp2;


		try {
			
			pasvSocket = new Socket(ipNew, portNew);
			
		} catch (UnknownHostException e) {
			System.out.println("Host unbekannt");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			fromPasvServer = new BufferedReader(new InputStreamReader(
					pasvSocket.getInputStream()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			writePasvCommands = new PrintWriter(pasvSocket.getOutputStream(),
					true);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		


		
	}
	
	public void LIST() throws IOException  {
	writeCommands.print("LIST\n");
	writeCommands.flush();
	
	}
	
	
	public void run() {
		try {
			connect();
	
	//		getStatus();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			USER();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		PASS();


		try {
			PASV();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public Client() throws IOException {
		
	}

	
	
	public static void main(String[] args) throws IOException, InterruptedException {
		Client test = new Client();
		Thread client = new Thread(test);
		client.start();
		
		Thread.sleep(300);
	
		
		Thread konsole = new Thread(new Konsole(test));
		konsole.setDaemon(true);
		konsole.start();
		
		
		
		Disrupter disrupt = new Disrupter(test);
		disrupt.start();
		
		
	
	}

	
	
}

eine nebenklasse

Java:
import java.io.IOException;


public class Konsole extends Thread {
	
	static int id = 0;
	
	Client client;
	
	public Konsole(Client client) {
		this.client = client;
	}
	
	public void run() {
		System.out.println("========= Konsole "+ ++id +" started");
		
	while(true) {
		
		
		try {
			
			String line = client.fromServer.readLine();
			synchronized(client.commands){
			client.commands.add(line);
				System.out.println(line);
			}
				if(line == null) {break;}
			
			
		} catch (IOException e) {}
		
	}
	
			
					
			
	}
}


exceptions

Exception in thread "Thread-2" java.util.NoSuchElementException
at java.util.Vector.lastElement(Vector.java:456)
at Client.getPasvCon(Client.java:93)
at Client.PASV(Client.java:82)
at Client.run(Client.java:174)
at java.lang.Thread.run(Thread.java:680)
 
Zuletzt bearbeitet:
und du kennst alle Abläufe?
ein paar System.out.println() hast du doch schon drin, baue mehr ein, etwa in Konsole
System.out.println("read line: .., save it in stack .. (hashcode, size)");
Ausgaben vor nach dem synchronized-Block wenn andere Abfragen dort nicht synchronisiert sind

sowie die Schritte in der run-Methode der Client-Klasse loggen bis hin zu den schlimm benannten PASV- + getPasvCon-Methoden,
findet alles in korrekter Reihenfolge statt?
frage auch im Client selber evtl. noch den hashcode des Stacks ab, der ist ziemlich deutlich zur Unterscheidung mehrerer
 
Tja, dein Stack ist leer und du willst auf das "last Element" zugreifen, darum die Exception.
Leider verwendest du den Stack so als wäre er ein Vector (er erbt ja davon aber warum dann Stack).
Stacks bedienst du normalerweise mit push und pop. Du musst aber auch überprüfen, ob dein Stack leer ist bzw diese Exception abfangen.
 
Das der Stack leer ist weiß ich, mein Problem war wieso 🙂
Aber ein Thread.Sleep hat das Problem gelöst. Da war der Schreibvorgang wohl schneller als die Erstellung
 
Unabhängig davon, sollte/muss überprüft werden, ob in dem Stack etwas enthalten ist, bevor man versucht etwas rauszuholen.
Und die Anmerkung: Warum Stack, wenn er doch nur als Vector benutzt wird ist auch berechtigt?
 

Neue Themen


Zurück
Oben