Stallo con Java process.waitFor()
DOMANDA:
Nell'eseguire un programma esterno con Runtime.exec(), perché se uso il metodo process.waitFor() va tutto in stallo?
package process;
import java.io.IOException;
public class ProcessTest {
public static void main(String[] args)
throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd /C C:\\ffmpeg -i C:\\input.avi C:\\output.avi");
process.waitFor();
System.out.println("FINE");
}
}
import java.io.IOException;
public class ProcessTest {
public static void main(String[] args)
throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd /C C:\\ffmpeg -i C:\\input.avi C:\\output.avi");
process.waitFor();
System.out.println("FINE");
}
}
RISPOSTA:
Eseguendo il codice della domanda, la stringa "FINE" non verrà mai eseguita. La causa del problema è la bufferizzazione di stdout e stderr. Infatti spesso capita che i dati in arrivo ai vari stream non siano sufficienti a riempire completamente i buffer. Quindi, finché i buffer non sono pieni, restano in attesa di input, lasciando il programma in stallo.
La soluzione è quindi forzarne lo svuotamento quando non ci sono altri dati in arrivo.
Ecco un modo per farlo (tra gli asterischi le aggiunte necessarie):
package process;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ProcessTest {
public static void main(String[] args)
throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd /C C:\\ffmpeg -i C:\\input.avi C:\\output.avi");
// **************************************************************
// prendiamo l'error stream
InputStream is = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println(br.readLine()); // lo svuotiamo
br.close(); // e lo chiudiamo
process.getOutputStream().flush(); // svuotiamo anche l'output stream
// **************************************************************
process.waitFor();
System.out.println("FINE");
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ProcessTest {
public static void main(String[] args)
throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd /C C:\\ffmpeg -i C:\\input.avi C:\\output.avi");
// **************************************************************
// prendiamo l'error stream
InputStream is = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println(br.readLine()); // lo svuotiamo
br.close(); // e lo chiudiamo
process.getOutputStream().flush(); // svuotiamo anche l'output stream
// **************************************************************
process.waitFor();
System.out.println("FINE");
}
}
In questo caso riusciremo nel nostro intento e la stringa "FINE" verrà finalmente visualizzata.
Commenti
Posta un commento