我正在尝试从java应用程序中启动VideoLAN程序的实例。我尝试这样做的方法之一如下所示:
Process p = Runtime.getRuntime().exec("\"C:\\Program Files\\VideoLAN\\VLC\\vlc.exe\" \"http://www.dr.dk/Forms/Published/PlaylistGen.aspx?qid=1316859&odp=true\" :sout=#std{access=udp,mux=ts,dst=127.0.0.1:63928}");
如果我执行上述命令,vlc程序将启动,并将启动流操作(它通过连接,缓冲然后流式传输)。
当Runtime exec(或ProcessBuilder启动)执行命令时,vlc程序将在缓冲阶段结束时挂起。如果java程序中的所有线程都终止/运行到结束,则vlc程序将进入流式阶段。在vlc进程关闭之前,java进程不会终止,因此这种行为显然是进程之间某种耦合的结果。
尝试通过将命令写入.cmd文件然后执行它来间接执行命令,但会导致相同的行为。
关于如何避免外部流程挂起的任何想法?
答案 0 :(得分:7)
嗯,我的猜测是VLC填满你的STDOUT缓冲区并挂在printf语句中,因为STDOUT正在等待该缓冲区清空。
您需要获取流程输出的流并读取它(即使您将其丢弃)。
我建议您阅读此article
在第4页是一个很好的例子,说明如何读取线程中的流,这样你的子进程就不会阻塞。
答案 1 :(得分:0)
这个网站很棒:)。出于某种原因,我认为已经尝试过的方法突然开始起作用。
问题是vlc写入stdErrOut(在提示中执行时不可见)。一旦某个输出缓冲区已满,它就会阻塞。解决方案是将stdErr重定向到stdOut,然后让一个线程清空进程对象的输入流。
然而,这不是最佳解决方案,因为我需要相当数量的外部进程,并且您无法在其输入流上执行非阻塞I / O.稍微试验一下,让计时器服务驱动器空读取多个进程。关于如何解决过程以避免此问题的其他建议非常受欢迎。