2009-06-22 6 views
0

Gibt es eine thread-sichere Möglichkeit, das stdout gleichzeitig von einem externen Prozess konsumieren, mit ProcessBuilder in Java 1.6?Gleichzeitig konsumieren stdout von einem externen Prozess

Hintergrund: Ich muss pbzip2 aufrufen, um große Dateien in stdout zu entpacken und jede Zeile zu verarbeiten, während die Datei dekomprimiert wird (pbzip2 verwendet im Gegensatz zu anderen Implementierungen mehrere CPUs).

Der logische Ansatz ist, ein Kind Thread zu Schleife über die Input zu erstellen (dh stdout, nicht lieben Sie gerade die Namensgebung?), Wie folgt:

while((line = reader.readLine()) != null) 
{ 
    // do stuff 
} 

jedoch unzipping langsam ist, so Was ich wirklich brauche, ist, dass die reader.Line-Methode ruhig darauf wartet, dass die nächsten Zeilen verfügbar werden, anstatt zu beenden.

Gibt es einen guten Weg, dies zu tun?

+1

Die reader.readLine() tut genau das, was Sie wollen. Ist Ihre Implementierung zu früh beendet? – akarnokd

+0

Nein, die Dokumentation, die ich hatte, gab nicht an, ob sie warten würde oder nicht, also habe ich mich gefragt, ob das threadsicher war - zum Beispiel ob readLine den Stream denken würde, wenn das Timing gerade vorbei wäre ist geschlossen. – Rob

Antwort

2

Sie sollten Ihren Eingabestream mit einem InputStreamReader und BufferedReader umhüllen können. Sie können dann readLine() anrufen und das wird wie erforderlich blockieren.

Beachten Sie, dass Sie einen entsprechenden Leser für den Stderr haben sollten. Sie müssen nichts damit anfangen, aber Sie müssen den stderr-Stream konsumieren, sonst blockiert der erzeugte Prozess möglicherweise. Siehe this answer für Links usw.

1

Sie haben mehr oder weniger die Lösung selbst. Sie erstellen einfach einen neuen Thread, der die nächste Zeile in einer Schleife aus dem Stream Ihres externen Prozesses liest und diese Zeile verarbeitet.

readLine() blockiert und wartet, bis eine neue Zeile verfügbar ist. Wenn Sie auf einem Multicore/Prozessor-Computer arbeiten, kann Ihr externer Prozess das Entpacken problemlos fortsetzen, während der Thread eine Zeile verarbeitet. Wenigstens kann das Entpacken fortgesetzt werden, bis die OS-Pipes/Puffer voll sind.

Beachten Sie, dass Sie das Entpacken blockieren, wenn Ihre Verarbeitung langsamer ist als das Entpacken, und an diesem Punkt wird es zu einem Problem mit Speicher und Geschwindigkeit. z.B. Sie könnten einen Thread erstellen, der nichts anderes tut, als Zeilen lesen (also wird das Entpacken nicht blockiert), puffert sie in einer Warteschlange im Speicher und einen anderen Thread - oder sogar mehrere -, der diese Warteschlange verbraucht.

Readline-Methode ruhig zu warten, die nächste Zeile (n) verfügbar wird, statt Verlassen

nd das ist genau das, was readline tun sollte, wird es nur blockieren, bis eine ganze Linie ist verfügbar.

1

Ja.

Ich habe etwas Code geschrieben, der einen zeitaufwändigen Job (ffmpeg) in einem Prozess (launched by process builder) startet, und es startet wiederum meine OutputStreamReader Klasse, die eine Erweiterung von Thread ist, die das stdio verbraucht und tut etwas Magie damit.

Der Haken (für mich) war das Umleiten des Fehlerstroms. Hier ist mein Code-Schnipsel:

 procbbuilder.redirectErrorStream(true); 
     proc = pb.start(); 
     err = new MyOutputStreamReader(this, proc.getInputStream()); //extenion of thread 
     err.start(); 

     int exitCode = proc.waitFor(); 
Verwandte Themen