关于Process调用shell建表脚本 进程阻塞

问题描述:我们有个功能需要通过java调用shell脚本进行建表。其中调用进程有两个方法,

1.Process类,Process ps = Runtime.getRuntime().exec(命令);

2.ProcessBuilder:

               ProcessBuilder hiveProcessBuilder = new ProcessBuilder(command);

               hiveProcessBuilder.start();

这两个都能用,其中我使用的是后面一个,但是存在一个问题,方法调用起来后,并不能直接生成脚本,后来发现只要重启服务,表就建好了,分析发现应该是调起的这个进程阻塞了,然后按照这个思路发现网上有人说法非常可能,应该是进程自己去处理stdout和stderr的输出,就是说,执行的结果不知道是现有错误输出(stderr),还是现有标准输出(stdout)。你无法判断到底那个先输出,所以可能无法读取输出,而一直阻塞。 例如:你先处理标准输出(stdout),但是处理的结果是先有错误输出(stderr),一直在等错误输出(stderr)被取走了,才到标准输出(stdout),这样就产生了阻塞。

解决办法:

  1. mport java.util.*;  
  2. import java.io.*;  
  3. class StreamGobbler extends Thread  
  4. {  
  5.     InputStream is;  
  6.     String type;  
  7.       
  8.     StreamGobbler(InputStream is, String type)  
  9.     {  
  10.         this.is = is;  
  11.         this.type = type;  
  12.     }  
  13.       
  14.     public void run()  
  15.     {  
  16.         try  
  17.         {  
  18.             InputStreamReader isr = new InputStreamReader(is);  
  19.             BufferedReader br = new BufferedReader(isr);  
  20.             String line=null;  
  21.             while ( (line = br.readLine()) != null)  
  22.                 System.out.println(type + ">" + line);      
  23.             } catch (IOException ioe)  
  24.               {  
  25.                 ioe.printStackTrace();    
  26.               }  
  27.     }  
  28. }  
  1. public class ExecRunner  
  2. {  
  3.     public static void main(String args[])  
  4.     {  
  5.         if (args.length < 1)  
  6.         {  
  7.             System.out.println("USAGE: java GoodWindowsExec <cmd>");  
  8.             System.exit(1);  
  9.         }  
  10.           
  11.         try  
  12.         {              
  13.             String osName = System.getProperty("os.name" );  
  14.             String[] cmd = new String[3];  
  15.             if( osName.equals( "Windows NT" ) )  
  16.             {  
  17.                 cmd[0] = "cmd.exe" ;  
  18.                 cmd[1] = "/C" ;  
  19.                 cmd[2] = args[0];  
  20.             }  
  21.             else if( osName.equals( "Windows 95" ) )  
  22.             {  
  23.                 cmd[0] = "command.com" ;  
  24.                 cmd[1] = "/C" ;  
  25.                 cmd[2] = args[0];  
  26.             } else {  
  27.                 StringTokenizer st = new StringTokenizer(command, " ");  
  28.                 cmd = new String[st.countTokens()];  
  29.                 int token = 0;  
  30.                 while (st.hasMoreTokens()) {  
  31.                     String tokenString = st.nextToken();  
  32.                     // System.out.println(tokenString);  
  33.                     cmd[token++] = tokenString;  
  34.                 }  
  35.             }  
  36.               
  37.             Runtime rt = Runtime.getRuntime();  
  38.             System.out.println("Execing " + cmd[0] + " " + cmd[1]   
  39.                                + " " + cmd[2]);  
  40.             Process proc = rt.exec(cmd);  
  41.             // any error message?  
  42.             StreamGobbler errorGobbler = new   
  43.                 StreamGobbler(proc.getErrorStream(), "ERROR");              
  44.               
  45.             // any output?  
  46.             StreamGobbler outputGobbler = new   
  47.                 StreamGobbler(proc.getInputStream(), "OUTPUT");  
  48.                   
  49.             // kick them off  
  50.             errorGobbler.start();  
  51.             outputGobbler.start();  
  52.                                       
  53.             // any error???  
  54.             int exitVal = proc.waitFor();  
  55.             System.out.println("ExitValue: " + exitVal);          
  56.         } catch (Throwable t)  
  57.           {  
  58.             t.printStackTrace();  
  59.           }  
  60.     }  
  61. }  

阻塞方法引用地址:https://tivan.iteye.com/blog/1045518

猜你喜欢

转载自blog.csdn.net/N_E_W_J_A_V_A/article/details/86647042