2014-01-30 115 views
0

这里是我有: 我有一个线程启动一个进程,这个进程是由ProcessBuilder创建的,并在终端启动一个字符串命令。有许多并发线程执行相同的操作,但数据不同。在java中,如何让一个线程等待一个进程完成?

这是我想要做的: 我想让一个线程(启动一个进程)等待该进程,直到完成。我想出了两种方法,但都没有工作。方法1:使用process.waitFor();方法1:使用process.waitFor();方法2:使用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的过程,每个过程的工作在不同的视频数据(没有数据依赖或种族的状况或什么那么这里)。所有这些线程1线程由另一个函数(main)中的另一个主线程创建并启动。 Linux中的操作系统。 IDE是Netbeans(这是我得到每个函数的描述)。我试图尽量缩短复制粘贴的代码(为了简单起见),所以如果您认为需要其他函数或其他程序的代码,请通知我将其粘贴到此处。

非常感谢你,

+0

你是如何开始你的线程?我严重怀疑Process.waitFor()冻结了所有的线程。 – Kayaman

+0

谢谢你的回答。线程由threadobject.start()启动,然后在主程序中启动threadobject.join()。不使用.join()会导致线程争夺他们的输入变量。 – user2452253

+0

那么,使用'.join()'会导致线程等待。 'Process.waitFor()'与它无关。 – Kayaman

回答

1

我相信你需要使用单独的线程来读取输入;我没有找到避免它的方法。我使用以下算法(in the H2 database),它对我来说工作正常。请注意0​​:

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(); 
} 
+0

谢谢你的回答。随着这段代码的一些修改,我的程序正在工作。这里唯一的缺点是现在创建的线程太多了。 – user2452253

+0

哦,顺便说一句,我必须删除该p.waitFor();再次因为它会导致旧问题,所有线程和进程都停止运行,除了正在等待的进程。 – user2452253

+0

我认为在这种情况下并不是真的需要p.waitFor(),但奇怪的是我使用它并从未看到它的任何问题... –

0

方法1与Process.waitFor()应该工作。我认为你开始错误的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(); 
     } 
    } 
} 

由于平过程比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(); 

我得到预期的输出。所以我认为你正在使用你的线程错误。

+0

你好,谢谢你的详细解答。然而,我以类似的方式启动线程。除了.start()之后,我必须使用.join()线程来防止任何竞争条件超过它们的输入变量。问题依然存在。 – user2452253

相关问题