also ohne mir jetzt den code zu ziehen ... in ne datei zu packen ... was drum rum zu basteln ... und dann zu versuchen es zu compilen ... kann ich dir jetzt schon sagen das das was du uns hier gepostet hast definitiv zu einem compile-error führen wird
dessweiteren ist auch die logik hinter diesem code auch nachem dritten mal durchlesen sehr schwer zu verstehen ... und selbst dann wundere ich mich noch das da was anderes steht als das ding eigentlich machen soll
ich denke du hast hier die falsche herangehensweise ...
erstmal solltest du dir überlegen : was genau willst du machen
dann : wie könnte man es implementieren ... pseudo-code hilft hier immer ein stück weiter ...
folgend : überprüfung der logik : gehe die einzelnen schritte einfach noch mal logisch durch und überprüfe ob das auch wirklich genau so läuft wie es gedacht ist ...
schlussendlich : implementierung und testen
grad was FTP angeht ... da braucht man einiges an wissen mehr als die bloße socket-kommunikation über den steuer-kanal ... vor allem muss man die unterschiede zwischen active und passive kennen und diese umsetzen können ...
aber ich will dich jetzt nicht entmutigen und versuch dir mal so gut ich kann zu helfen
das erste was mir aufgefallen ist waren diese schrecklichen THROWS-konstrukte
wenn das ganze nur zum testen in der entwicklung ist kannst du ruhig throws Exception oder sogar throws Throwable verwenden um einfach mal alles an die VM zu deligieren
später im produktiven einsatz solltest du dann solche throws-konstrukte vermeiden *außer wo es wirklich sinn macht* und in den methoden selbst mit try-catch-finaly - blöcken darauf reagieren ...
dabei ist die reihen folge zu beachten ...
java.lang.Throwable
ist die basis-klasse ... wenn du dir nicht sicher bist was geworfen wird einfach Throwable nehmen
java.lang.Throwable hat zwei dierekte sub-klassen
java.lang.Error und java.lang.Exception
beide für unterschiedliche aufgabenbereiche ...
das meiste wird sicher über Exception laufen ...
Error hingegen beinhaltet sub-klassen die laut api nicht in einem catch-block oder einer throws-clause abgefangen werden sollten ...
Error und seine sub-klassen stellen abnormale probleme der gesamten VM dar und sind speziell dafür gedacht die VM bewusst dadurch "abzuschießen"
Exception hingegen wird verwendet wenn bewusst gefordert wird das auftretende fehler abgefangen und behandelt werden
und jetzt kommt die hirarchie der Exception's ins spiel ...
sehen wir uns mal deinen code an ...
einmal steht FTPException VOR der IOException ... und einmal dahinter ...
welches ist nun aber richtig ... das hängt vorallem von der implementation der FTPException ab
da diese in java selbst nicht spezifiziert ist muss man nun kuggn welche die super-klasse von FTPException ist ...
die meisten FTPException-implementationen die mir google liefert sind dierekt von Exception abgeleitet und stehen damit auf der selben stufe wie IOException ...
auch ableitungen von RuntimeException stehen effektiv mit IOException auf der selben stufe ...
hier ist also die reihenfolge wirklich egal ...
wenn FTPException aber nun von IOException *oder einer der sub-klassen* abgeleitet ist muss definitiv ERST die FTPException abgefangen werden und DANN erst die IOException ...
nehmen wir mal als beispiele eine SocketException
diese wird wie folgt abgeleitet
>java.lang.Object
>>java.lang.Throwable
>>>java.lang.Exception
>>>>java.io.IOException
>>>>>java.net.SocketException
damit müsst also in einem try-catch block
Java:
try
{
//code
}
catch(SocketException se) { }
catch(IOException ioe) { }
catch(Exception e) { }
sowas hier kommen um die Exceptions ihrer hirarchie-stufe umgekehrt abzufangen ...
wenn du es andersrum schreiben würdest würdest du auch bei einer konkreten SocketException nie in den se-block kommen die IOException oder Exception drüber stehen und es abfangen würden wenn diese ÜBER der SocketException stehen würden ... also darauf achten um richtig zu catchen
was jetzt dein problem mit den Threads angeht
Threads sind dazu da um mehrere teile deiner app parallel laufen zu lassen ... also "quasi"-gleichzeitig
erklärung : sehen wir uns mal eine normale java-app an ...
du wirst erkennen das die app einer festgelegten reihenfolge folgt und immer nur genau eins nach dem anderen macht
um dem auf moderenen multi-process und multi-thread system endgegenzuwirken und diese fähigkeit nutzbar zu machen wurden Threads erfunden ...
damit kannst du mehrere teile gleichzeitig laufen lassen ...
z.B. die verarbeitung von daten und gleichzeitiges warten auf neue daten vom und zusätzlich grad welche zum server hinschicken ...
durch mehrere threads lassen sicher aber auch leicht DEADLOCKS erzeugen ... vorallem wenn die app so aufgebaut ist das es keinen theoretischen fehlerfall gibt und darauf verzichtet wurde die threads zu synchronisieren
DEADLOCKS sind meist logik-fehler ...
sie entstehen dadurch das sich mehrere Threads (in)dierekt gegenseitig blockieren
zum beispiel das ein thread auf daten wartet und der zweite *der eigentlich zum senden beauftragt wurde* nichts tut weil der erste ihm nicht sagt DAS er was tun soll und WAS er tun soll ...
allerdings ist das problem das der erste thread nichts macht ohne daten zu bekommen ... was wiederum nur ausgelöst wird wenn der zweite thread daten sendet ...
das ist einer der häufigsten DEADLOCKS ... gibt noch ne reihe anderer schöner beispiele
wenn du jetzt unvorhergesehende daten lesen willst ... also bei denen du nicht weist OB bzw WANN diese kommen ... baust du dir einfach einen thread in dem dauerhaft auf eingehende daten gewartet wird ...
um jetzt allerdings dem DEADLOCK vorzubeugen musst du diesen thread davon abhalten daten zu lesen wenn du gerade in einem anderen thread auf diese daten wartest ...
das tut man in der regel mit BOOL-variablien die dann geprüft werden ...
nach dem du die daten hast die du haben wolltest änderst du diesen bool-wert einfach wieder und der andere thread beginnt wieder mit seiner arbeit ...
dazu dürfte auch i-wo im netz pseudo-code rumfliegen
du siehst also ... das ganze ist garnicht so schwer wie du es dir gerade machst ...
und mit dem synchronized meinte ich eigentlich das man nur entsprechende getter / setter sinnvollerweise synchronized machen sollte ... aber halt nur da wo es notwendig ist ...
weil wenn du gleich die ganze app synchronized brauchst du keine threads mehr ...