并发(十二):JAVA调用外部进程

来源:互联网 发布:moeloader 类似软件 编辑:程序博客网 时间:2024/05/13 04:03

从JAVA 1.5版本开始,JAVA新增了ProcessBuilder,专门用于调用外部进程,且能快速创建一个指定了环境的进程与子进程,极大地增强了进程的复用性,示例代码如下:

//  定义在FileNameGetProcess.java文件中static List<String> call() throws Exception {    List<String> fileNames = Lists.newArrayList();    //  设置了环境变量DIR,针对Windows环境    List<String> commands = Lists.newArrayList("cmd.exe", "/c", "dir /w", "%DIR%");    ProcessBuilder pb = new ProcessBuilder(commands);    //  设置环境变量    Map<String, String> env = pb.environment();    env.put("DIR", "D:\\");    //  启动进程    Process pr = pb.start();    InputStream is = pr.getInputStream(); // 获得输入流    InputStreamReader isr = new InputStreamReader(is, "GBK");// 创建输入读流,编码方式为GBK    BufferedReader br = new BufferedReader(isr); // 创建读缓冲对象    while ((line = br.readLine()) != null) {        // 循环读取数据        fileNames.add(line);    }    pr.waitFor();    return fileNames;}

在上述代码的执行中,一定要密切注意命令参数,JAVA执行命令都通过实体文件的方式,所以执行的命令如果没有物理文件支持,如dir,则一定要采用“cmd.exe”的方式,而对于有物理文件支持的命令,如C:\Windows\System32文件下的ipconfig命令以及脚本,直接给出文件调用路径及命令即可,如:

//  直接调用ProcessBuilder pb = new ProcessBuilder("ipconfig", "/all");Process pr = pb.start();//  直接调用ProcessBuilder pb = new ProcessBuilder("E:\\list.cmd");Process pr = pb.start();

如果违反了上述规则,则一定会出现如下错误:

Exception in thread "main" java.io.IOException: Cannot run program "dir c:\": CreateProcess error=2, 系统找不到指定的文件。    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)    at com.cnitsec.mirana.process.CMDExecute.main(CMDExecute.java:106)Caused by: java.io.IOException: CreateProcess error=2, 系统找不到指定的文件。    at java.lang.ProcessImpl.create(Native Method)    at java.lang.ProcessImpl.<init>(ProcessImpl.java:386)    at java.lang.ProcessImpl.start(ProcessImpl.java:137)    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)    ... 1 more

为了使进程的执行具有更好的响应性,我们可以使用Future对进程执行的任务进行封装,如下:

ExecutorService executor =  Executors.newSingleThreadExecutor();//  获取执行结果Future<List<String>> results = executor.submit(FileNameGetProcess::call);List<String> strs = results.get();for(String str: strs) {    System.out.println(str);}//  一定要记得关闭,否则主线程无法结束executor.shutdown();

结论

外部进程的执行状态可以通过Future方式来获取执行结果,ProcessBuilder.start()还支持InterruptedException,所以外部进程在执行过程中,还支持主线程的中断信号。

原创粉丝点击