[英]In java, how to make a single thread to wait for a process to finish?
這是我擁有的:我有一個線程來啟動一個進程,該進程由ProcessBuilder創建,並在終端中啟動一個字符串命令。 有許多並發線程執行相同的操作,但是對不同的數據執行。
這是我想做的事情:我想創建一個線程(啟動了一個進程)以等待該進程完成。 我想出了兩種方法,但都沒有用。
方法1:使用process.waitFor(); 這會導致所有並發線程都等待一個進程(通常是第一個進程)完成。 waitFor();的描述 說,它使一個線程等待,但這不是它的工作,實際上使所有線程等待。 因此,該程序不再是並發的。
方法2:運行另一個線程,該線程從該進程中讀取管道流,等到有流之后,再運行應該在該進程之后運行的函數。 缺點是現在有很多線程,所以我不想使用這種方法。 這種方法的另一個問題是讓我感到困惑,我應該使用流程的哪些屬性? OutputStream,InputStream或ErrorStream?
這是代碼:
public class Thread1 extends Thread{
private String[] incommand; //this is the command for the process builder
private String newoutputfile;
InputStream ins = null;
Reader r = null;
BufferedReader br = null;
ProcessBuilder pbtx = null;
public Thread1(String[] incommand, String newoutputfile){
super("Thread1");
this.incommand = incommand;
this.newoutputfile = newoutputfile;
this.pbtx = new ProcessBuilder();
}
@Override
public void run(){
try{
pbtx.command(incommand);
Process ptx = pbtx.start();
//to make sure job is done
ptx.waitFor(); //problem is apparently here
// made sure job is done
//the next function is supposed to run after the process is finished
rite();
//
} catch (IOException ex){
System.out.println("exception in thread t1");
ex.printStackTrace();
}
catch (InterruptedException yo){
System.out.println("exception in thread t1");
}
}
順便說一句,該進程是一個ffmpeg進程,每個進程都在不同的視頻數據上工作(沒有數據依存關系或競爭條件,或者在這里如此)。 所有這些thread1線程都是由另一個函數(main)中的另一個主線程創建和啟動的。 Linux中的操作系統。 IDE是Netbeans(可以從中獲得每個功能的描述)。 我試圖使復制粘貼的代碼盡可能短(為簡單起見),因此,如果您認為需要其他功能或程序其余部分的代碼,請通知我將其粘貼在此處。
非常感謝你,
我相信您確實需要使用單獨的線程來讀取輸入。 我沒有找到避免這種情況的方法。 我使用以下算法( 在H2數據庫中 ),對我來說效果很好。 另請注意redirectErrorStream
:
ProcessBuilder pb = new ProcessBuilder();
pb.command(cmd.array());
pb.redirectErrorStream(true);
Process p = pb.start();
copyInThread(p.getInputStream(), quiet ? null : sysOut);
p.waitFor();
return p.exitValue();
private static void copyInThread(final InputStream in, final OutputStream out) {
new Thread() {
@Override
public void run() {
try {
while (true) {
int x = in.read();
if (x < 0) {
return;
}
if (out != null) {
out.write(x);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} .start();
}
具有Process.waitFor()的方法1應該可以工作。 我認為您啟動Thread1錯誤。
這是一個簡單的例子。 您可以復制並嘗試。 StackOverflowPinger
開始新的ping過程。
public class StackOverflowPinger implements Runnable{
public StackOverflowPinger(int id){
this.id = id;
}
private int id;
@Override
public void run() {
try {
ProcessBuilder pbuilder = new ProcessBuilder();
Process pingprocess = pbuilder.command("ping", "www.stackoverflow.com").start();
int pingresult = pingprocess.waitFor();
if(pingresult == 0)
System.out.println("Pinger Nr." + this.id + " successfully pinged stackoverflow.");
} catch (IOException | InterruptedException e) { e.printStackTrace(); }
}
}
睡眠Sleeper
睡眠250毫秒。
public class Sleeper implements Runnable{
public Sleeper(int id){
this.id = id;
}
private int id;
@Override
public void run() {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Sleeper " + this.id + " finished sleeping.");
}
}
這是實例化並啟動線程的Main。
public class ProcessMain {
public static void main(String[] args) {
for(int i = 0 ; i<4; i++){
new Thread(new StackOverflowPinger(i)).run();
new Thread(new Sleeper(i)).run();
}
}
}
由於ping過程花費的時間遠遠超過250毫秒,因此預期的輸出應該是這樣的。
Sleeper 3 finished sleeping.
Sleeper 0 finished sleeping.
Sleeper 1 finished sleeping.
Sleeper 2 finished sleeping.
Pinger Nr.0 successfully pinged stackoverflow.
Pinger Nr.1 successfully pinged stackoverflow.
Pinger Nr.3 successfully pinged stackoverflow.
Pinger Nr.2 successfully pinged stackoverflow.
但是實際的輸出是這樣的。
Pinger Nr.0 successfully pinged stackoverflow.
Sleeper 0 finished sleeping.
Pinger Nr.1 successfully pinged stackoverflow.
Sleeper 1 finished sleeping.
Pinger Nr.2 successfully pinged stackoverflow.
Sleeper 2 finished sleeping.
Pinger Nr.3 successfully pinged stackoverflow.
Sleeper 3 finished sleeping.
只有當我改變線
new Thread(new StackOverflowPinger(i)).run();
new Thread(new Sleeper(i)).run();
至
new Thread(new StackOverflowPinger(i)).start();
new Thread(new Sleeper(i)).start();
我得到了預期的輸出。 所以我認為您使用的線程錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.