2017-07-28 33 views
1

我有一個Java項目,它有助於使用youtube-dl查找youtube播放列表中的所有視頻信息。這裏是Main.javajava block while using shell命令使用進程

import java.io.*; 


public class Main { 

public static void main(String[] args) throws Exception { 
    String command1 = "/usr/local/bin/youtube-dl --flat-playlist --dump-single-json https://www.youtube.com/playlist?list=PLFcOH1YaRqUo1yEjY5ly09RFbIpUePF7G"; 
    String command2 = "/usr/local/bin/youtube-dl --flat-playlist --dump-single-json https://www.youtube.com/playlist?list=PLC6A0625DCA9AAE2D"; 
    System.out.println(executeCommand(command1)); 

} 

private static String executeCommand(String command) throws IOException, InterruptedException { 
    int exitCode = 0; 
    String result = ""; 
    Process process; 
    ProcessBuilder builder = new ProcessBuilder(command.replaceAll("[ ]+", " ").split(" ")); 
    builder.directory(new File("/tmp/test")); 
    process = builder.start(); 
    exitCode = process.waitFor(); 
    return getStringFromInputStream(process.getInputStream()); 
} 
private static String getStringFromInputStream(InputStream is) { 

    BufferedReader br = null; 
    StringBuilder sb = new StringBuilder(); 

    String line; 
    try { 

     br = new BufferedReader(new InputStreamReader(is)); 
     while ((line = br.readLine()) != null) { 
      sb.append(line); 
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (br != null) { 
      try { 
       br.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
    return sb.toString(); 
} 
} 

command1command2是除了Youbute播放列表參數是相同的。 command2中的播放列表中有409個視頻,並且在command1中有200個視頻。我可以在終端中成功獲得兩個命令的結果。只是command2需要更多的時間,但只有幾秒鐘。但是當我運行Main.java(javac Main.java; java Main)時,對於command1,它會成功打印結果,但對於command2,它在那裏掛起幾分鐘而沒有任何結果。這裏是jstack這個過程

"main" #1 prio=5 os_prio=0 tid=0x00007f828c009800 nid=0xce7 in Object.wait() [0x00007f8293cf7000] 
java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <0x0000000771df9fe0> (a java.lang.UNIXProcess) 
    at java.lang.Object.wait(Object.java:502) 
    at java.lang.UNIXProcess.waitFor(UNIXProcess.java:396) 
    - locked <0x0000000771df9fe0> (a java.lang.UNIXProcess) 
    at Main.executeCommand(Main.java:18) 
    at Main.main(Main.java:8) 

它掛在exitCode = process.waitFor();。我不知道這件事。誰能幫我?非常感謝。

+0

您是否嘗試過在您的IDE中添加幾個斷點並在執行代碼時逐步查看它掛起的位置? –

+1

@KevinHooke我掛在exitCode = process.waitFor();我只是更新了問題並添加了jstack。 – user2256235

+0

設置一個斷點並將解析後的命令行(全部替換之後)在shell中運行,看看是否有效。也許最後的命令在代碼中呈現錯誤。 – zuckermanori

回答

1

如評論中所述,默認情況下,子過程的輸出被髮送到可以使用Process.getInputStream()讀取的管道。如果子進程生成大量輸出並且Java程序沒有使用它,則管道的緩衝區將被填滿,並且子進程將在寫入時阻塞。

最簡單的解決方案是在ProcessBuilder上調用.inheritIO()。這會將輸出發送到控制檯,而不是將其緩存到內存中(對於輸入和錯誤流也是如此)。