ERLEDIGT
JA
JA
ANTWORTEN
18
18
ZUGRIFFE
1321
1321
EMPFEHLEN
-
11.05.11 08:32 #1Toni86 Tutorials.de Gastzugang
Hallo,
ich habe folgendes Problem: ich starte aus einem Java-Programm (P1) ein anderes Java-Programm (P2, Client). Dieses kommuniziert mit (P3, Server, unwichtig) und erzeugt nach einer unbestimmten aber endlichen Zeit eine Datei und wird beendet. Nachdem ich von P1 aus P2 gestartet habe, möchte ich als nächstes die von P2 erzeugte Datei lesen, ich muss also darauf warten.
P2 starte ich mittelsoder über einen ProcessBuilder; macht hier bez. meines Problems aber keinen Unterschied. Falls ich es über Runtime mache, kann ich zum WartenCode :1
process = Runtime.getRuntime().exec(commandRunClient);
verwenden. Wenn ich es über ProcessBuilder mache, habe ich eine Schleife, die immer perCode :1
process.waitFor();
wartet und dann prüft, ob die Datei erzeugt wurde.Code :1
Thread.sleep(1000);
In beiden Fällen stelle ich Fest, dass P2 unterbrochen oder blockiert wird, da P3 (der Server) "Client timeout" meldet. Wenn ich nicht auf die Datei warte, und P1 ohne die erwartete Datei beendet wird, läuft P2 ohne "Client timeout" weiter. Es liegt also definitiv daran, dass waitFor() und Thread.sleep() den Prozess blockieren. Meine Frage: Kann man das verhindern? Wenn ja, wie?
Hier ein Code-Auszug für den Fall mit ProcessBuilder:
Code :1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
ProcessBuilder pb; Process processController; try { String commandRunClient = "command to start... specified somewhere else"; pb = new ProcessBuilder("cmd", "/c", commandRunClient); processController = pb.start(); } catch (IOException e) { System.out.println("evaluate(): error while trying to run the Controller"); e.printStackTrace(); } // Waiting for the file with the results or for timeout File resultsfile = new File(resultsFilename); boolean timeout = false; int seconds = 0; while ((!resultsfile.exists()) && (!timeout)) { try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("evaluate(): interrupted while waiting for the results"); e.printStackTrace(); } seconds++; if (seconds > 90) { timeout = true; processController.destroy(); } }
Viele Grüße,
Toni
-
11.05.11 09:28 #2SE Tutorials.de Gastzugang
Also erstens : wenn du mit ProcessBuilder arbeitest erhälts du genau so ein Process wie über die Runtime-Methode da du dem ProcessBuilder ja auch sagen musst das er starten soll. Und ProcessBuilder.start() liefert ein Process zurück ... und auf diesen kannst du genau so waitFor() anwenden. Also nächste mal bitte einen Blick in die Doc werfen.
Das Problem selber sollte damit allerdings nicht so im Zusammenhang stehen wie du es beschreibst da der ChildProcess ein eigenständiger Process ist und somit vom ParentProcess so einfach nicht manipuliert werden kann. Das Problem wird denke ich der File-Caller sein. Damit hängst du nämlich einen exklusive-Lock auf das File was natürlich den ChildProcess blockiert. Versuche mal deinen Code ab Zeile 12 einfach nur das Process.waitFor() und erst DANACH das File-Objekt zu erzeugen. Das sollte das Lock-Problem lösen. Das ganze ist nämlich ein sog. DEADLOCK : der ParentProcess wartet bis der ChildProcess eine Datei erstellt hat die der ChildProcess aber nicht erstellen kann da er auf die Freigabe des File-Locks des ParentProcess wartet. Ist eigentlich ein sehr einfaches Problem wenn man weis was da genau passiert.
-
11.05.11 09:38 #3Toni86 Tutorials.de Gastzugang
Da habe ich mich missverständlich ausgedrückt: natürlich kann ich darauf auch waitFor() anwenden, allerdings ist das IMMER ein endloses warten, wenn der Prozess über ProcessBuilder.start() aufgerufen wurde, siehe Doc
. Es bringt nichts, deshalb setze ich es mit nicht anwendbar gleich (ist einfach nicht praktikabel).
Danke für den Hinweis. Das könnte später noch zu Problemen führen. Allerdings kommt es momentan noch nicht dazu, denn der Child-Process erzeugt die Datei erst ganz am Ende seiner Ausführung (Ergebnisdatei). Der Timeout bzw. die Blockierung findet aber während seiner "Hauptausführungszeit" statt, also bevor eine Methode aufgerufen wird, die eine Datei erzeugt. Ich kann ausschließen, dass es MOMENTAN am File Lock liegt.
-
11.05.11 10:02 #4SE Tutorials.de Gastzugang
Gut,
erklär mir bitte erstmal warum es ein IMMER ENDLOS ist wenn du über ProcessBuilder.start().waitFor() auf den ChildProcess wartest ... das wird mir aus der Doc nicht ersichtlich.
Zweitens : Poste doch einfach mal den komplette code alle 3 beteiligten Programme so das wir uns ein lauffähiges Sample zusammencompilen können ums zu debuggen. Weil das bisschen Source da oben hilft so überhaupt nicht da daraus nicht ersichtlich wird das der ChildProcess nicht am File-Lock hängen bleibt. Eher im gegenteil wird diese Vermutung durch den Source nur noch bestärkt.
Es wäre mit sicherheit auch interessant was der ChildProcess alles macht und was da übers Netz geht und wie der Server reagiert. Vielleicht liegt der Fehler nicht in dem oben gepostetem Launcher sondern ganz wo anders ... aber das können wir nur vermuten ohne ein vollständig compilebares Beispiel bei dem der beschriebene Fehler auftritt. Versuch doch mal in deinem "Clienten" die ganze Netz-Kommunikation rauszunehemen und nur das File zu erstellen *meinet wegen mit Random-Daten*. Wenn hierbei der Fehler nämlich nicht auftritt liegt der Wurm im Netz-Teil den du dann auch mal posten müsstest ... und zwar beide Seiten ... nicht nur eine.
Aber so kann dir glaube ich nur jemand helfen desse Glaskugel weder kaputt noch im Urlaub ist, was bei so ziemlich jedem hier zutrifft. *Es gibt auch n paar die ihre Kugel zum Upgraden gegeben haben ... aber das dauert bekanntlich 4 - 6 Wochen*
-
11.05.11 10:25 #5Toni86 Tutorials.de Gastzugang
Hallo,
ich kann leider kein lauffähiges Code-Beispiel einstellen, weil ich mit größeren Frameworks arbeite. Ich kann auch wirklich ausschließen, dass es am File Lock liegt. Ich dachte, dass man das Problem "konzeptuell" also ohne viel Code lösen könnte. Ich beschreibe nochmal genauer, was passiert:
In meinem Hauptprogramm passiert in einem Durchlauf folgendes:
1. Ich generiere ein Java-Programme (Client), konkret: eine Klasse als .java-Datei. - funktioniert einwandfrei
2. Ich kompiliere diese Klasse über die Konsole per Command über Runtime.getRuntime().exec(...); und warte per waitFor() bis die Kompilierung abgeschlossen ist. - funktioniert einwandfrei
3. Ich starte den Server per Runtime.getRuntime().exec(...); - funktioniert einwandfrei
4. Ich starte den eben kompilierten Client. - funktioniert
5. Nun muss ich darauf warten, dass der Client beendet wird oder er eine Datei erzeugt hat (hier: äquivalente Ereignisse bei fehlerfreier Ausführung!)
Das Warten - egal in welcher Weise - blockiert dann den Client. Ich habe folgende Vermutung: das waitFor() beim Kompilieren funktionierte, weil javac (Compiler) ein anderes Programm ist als java (JRE). Der Client läuft aber wie das Hauptprogramm unter java (JRE). Und wenn ich dann java (JRE) warten lasse, wartet eben alles. Ich vermute weitehin, dass eine Lösung möglich wäre, wenn man die Ausführung des Clients als zusätzlichen Prozess oder Thread realisiert, aber ich weiß nicht wie. Per Process wird offenbar nur ein Unterprozess erzeugt, kein paralleler.
Vorschläge?
-
Hi,
könntest Du bitte mal die Zeile posten, die Du zum Starten des Clients (P2) verwendest.
Bzw. hast Du schonmal getestet, ob es funktioniert, wenn Du den Client nicht innerhalb Deines Programms startest, sondern manuell. Vielleicht klemmt dort noch etwas.
Gruß twagiGeändert von twagi (11.05.11 um 10:40 Uhr)
-
11.05.11 10:44 #7Toni86 Tutorials.de Gastzugang
Hallo,
das ist die im ersten try-Block im Code-Beispiel meines ersten Beitrages. Alternativ habe ich auchversucht. Macht aber keinen Unterschied. Das übergebene Kommando ist jeweils "java -cp <CLASSPATH> <anypackage>.Client" und funktioniert.Code :1
processController = Runtime.getRuntime().exec(commandRunClient);
Grüße,
Toni
-
Hi,
Du startest eine neue JVM, also einen neuen Prozess. Daher sollte es keine Auswirkungen haben, wenn Du in der einen VM auf ein Ergebnis aus der anderen wartest.
Wenn Du den Client so startest wird die Datei erzeugt?
Gruß twagi
-
11.05.11 11:05 #9Toni86 Tutorials.de Gastzugang
Hi,
nein, dazu kommt der Client nicht, weil er offenbar blockiert wird. Der Server meldet in dem Fall wie gesagt "Client timeout". Wenn ich im Hauptprogramm nicht auf den Client/die Datei warte, sondern mit Dummy-Ergebnissen weitermache, dann wird der Client ausgeführt und der Server meldet kein "Client timeout". Das Warten auf den Client blockiert wohl selbigen.
Grüße,
Toni
-
11.05.11 12:19 #10SE Tutorials.de Gastzugang
Wie wäre es dann mal mit Debuggen ? Also in den Clienten wirklich jede Anweisung mit sowas umschließen:
Dann kannst du nämlich genau sehen WO er genau hängt ... denn die Fehlermeldung vom Server sagt eigentlich nichts aus außer das der Socket irgendwie zusammenbricht.
-
11.05.11 12:58 #11
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Hi.
Kann es sein, das evtl. der Client eine Exception wirft? Diese wird ja gerne mal länger und vermutlich auf die Standarderrorausgabe geschrieben. Wenn der Puffer der Standarderrorausgabe voll läuft und niemand die Ausgabe ausliest, blockiert der Client.
Kombiniere Standarderror- und Standardausgabe (redirectErrorStream) und lies die Ausgabe während du auf Beendigung des Clients wartest und schließe den OutputStream des Prozesses.
GrußIf at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
11.05.11 13:07 #12Toni86 Tutorials.de Gastzugang
Hallo,
der Client läuft fehlerfrei. Wenn ich ihn nicht aus dem Programm heraus, sondern händisch über die Konsole starte (Server ebenfalls) funktioniert alles.
Es ist sogar so: wenn ich zB 30 Sekunden auf den Client warte, wird er 30 Sekunden lang blockiert (Server meldet "Client timeout"), denn wenn ich danach ohne die Ergebnisdatei weitermache, läuft auch der Client plötzlich (aber zu spät) und der Server meldet keinen Timeout mehr.
Grüße,
Toni
-
11.05.11 13:44 #13SE Tutorials.de Gastzugang
Gut ... ich versuch es jetzt mal so auszudrücken : Ich muss meine Glaskugel erst noch vom Boden kratzen.
Vielleicht kannst du dir dann n Plan machen was du schreiben solltest anstellen dem was du bisher geschrieben hast.
PS an die andere : last mir bitte wenigstens das einemal den Spass =P
-
12.05.11 16:25 #14Toni86 Tutorials.de Gastzugang
Hallo,
für die Nachwelt: ich habe das Problem selbst gelöst. Der Prozess wurde blockiert, weil durch Thread.sleep die komplette JVM einschläft, also auch das gestartete Java-Programm. Damit viel diese Möglichkeit ganz weg. Die Variante mit process.waitFor() hat das gestartete Programm blockiert, weil der Prozess die ganze Zeit damit beschäftigt war, über Streams zu kommunizieren, was ich aber nicht benötigte. Ergo: Zur Lösung des Problems habe ich die Streams geschlossen und schon funktionierte alles. process.waitFor() wartet nun bis der Prozess zu Ende ist und dann gehts weiter im Hauptprogramm.
Hier der Code:
Code :1 2 3 4 5 6 7 8 9 10 11 12 13
// Start the process clientProcess = Runtime.getRuntime().exec(commandRunClient); // Close all streams because they are uninteresting and otherwise the // program would wait endlessly for the termination of the process clientProcess.getErrorStream().close(); clientProcess.getInputStream().close(); clientProcess.getOutputStream().close(); // Wait until the client was terminated System.out.println("Waiting while Client is running..."); clientProcess.waitFor(); System.out.println("...done!");
-
12.05.11 16:29 #15
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
If at first you don't succeed, try again. Then quit. No use being a damn fool about it.
Ähnliche Themen
-
Thread.sleep() funktioniert nicht korrekt
Von d4rkY89 im Forum JavaAntworten: 4Letzter Beitrag: 14.03.10, 19:13 -
Thread.Sleep(); in Flex?
Von Wanabe_Flex im Forum Adobe Flex & AIRAntworten: 1Letzter Beitrag: 03.12.08, 18:00 -
Process ID von externen Prozess
Von Florian Strienz im Forum JavaAntworten: 0Letzter Beitrag: 13.02.08, 15:49 -
genaues Thread.sleep()
Von dontschew im Forum JavaAntworten: 2Letzter Beitrag: 16.12.07, 12:51 -
Process = Thread?
Von kahuna im Forum .NET ArchivAntworten: 1Letzter Beitrag: 11.08.04, 19:21





Zitieren
Login





