Java中Process类的使用与注意事项说明

目录
  • Process类的使用与注意事项说明
    • 1、在项目开发中
    • 2、在这里就需要认识一下process类
    • 3、来说说今天业务需求[waitfor()]:
    • 4、前不久遇到一个奇怪的问题就是ajax调用没有返回值
  • java的Process深入讲解

Process类的使用与注意事项说明

1、在项目开发中

经常会遇到调用其它程序功能的业务需求,在java中通常有两种实现方法

Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(cmd);
Process p=new ProcessBuilder(cmd).start();

2、在这里就需要认识一下process类

process是一个抽象的类,它包含6个抽象的方法

abstract public OutputStream getOutputStream();
abstract public InputStream getInputStream();
abstract public InputStream getErrorStream();
abstract public int waitFor() throws InterruptedException;
abstract public int exitValue();
abstract public void destroy();

process类提供获取子进程的输入流、子进程的输出流、子进程的错误流、等待进程完成、检查进程的推出状态以及销毁进程的方法;在这里需要提及的是创建的子进程没有自己的控制台或终端,其所有的io操作都是通过(输入流、输出流、错误流)重定向到父进程中。

3、来说说今天业务需求[waitfor()]:

我需要在linux下首先将一个文件copy到指定的文件夹下面,之后需要将该文件夹下面的文件加入指定的jar中,那么问题就来了,必须保证其先后顺序,也就书说再执行第二个命令的时候第一个命令必须完成。

    public void cmd(String cmd){
        try {
            Process ps= Runtime.getRuntime().exec(cmd);
        } catch (Exception e) {
            logger.info(e.getMessage(),e);
        }
    }

main函数如下:

public static void main(String[] args){
     String copy="cp -rf "+source+" "+target;
     String jar="jar -uvf "+jar+" "+file;
     cmd(copy);
     cmd(jar);
}

但是结果是新生成的jar中压根没有新加入的文件,但是文件确实copy到了指定的文件夹中,也就是谁两个命令都执行了,问题的关键就是“异步”,这时候需要waitFor()的介入

    public void cmd(String cmd){
        try {
            Process ps= Runtime.getRuntime().exec(cmd);
            ps.waitFor();
        } catch (Exception e) {
            logger.info(e.getMessage(),e);
        }
    }

那么问题就解决了!

4、前不久遇到一个奇怪的问题就是ajax调用没有返回值

我在service中实现了process的调用。

String[] commands = { commandGenerate,commandPublish};
        PrintWriter printWriter = response.getWriter();
        for (String comm : commands) {
            Runtime runtime = Runtime.getRuntime();
            try {
                logger.info("command is :{}",comm);
                Process process = runtime.exec(comm, null, null);
                BufferedInputStream inputStream = new BufferedInputStream(
                        process.getInputStream());
                BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(inputStream));
                String line;
                while (bufferedReader.read() != -1) {
                    line = bufferedReader.readLine();
                    System.out.println(line);
                }
                bufferedReader.close();
                inputStream.close();
                printWriter.println("success");
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                printWriter.println(e.getMessage());
            }
        }
        printWriter.flush();
        printWriter.close();

对应的controller为:

       State state = new State();
        String message="";
        try {
            message = missionService.syntax(taskName, response);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        state.setSuccess(true);
        state.setMessage(message.trim());
        return state;

打印state.getMessage()确实可以获得值,但是state返回就是空,刚开始以为是ajax的timeout时间的问题:修改了ajax的timeout时间仍然不行;将message直接赋值,然thread等待20s,结果是可以返回的,所以问题最终定为于service的这段实现。

原因分析:在上面提及了,process创建的子进程没有自己的控制台或终端,其所有的io操作都是通过(输入流、输出流、错误流)重定向到父进程中,如果该可执行程序的输入、输出或者错误输出比较多的话,而由于运行窗口的标准输入、输出等缓冲区有大小的限制,则可能导致子进程阻塞,甚至产生死锁,其解决方法就是在waitfor()方法之前读出窗口的标准输出、输出、错误缓冲区中的内容。

for (String comm : commands) {
            logger.info("the comm time is:"+new Date().getTime()+" the comm is:"+comm);
            Runtime runtime = Runtime.getRuntime();
            Process p=null;
            try {
                 p = runtime.exec(comm ,null,null);
                 final InputStream is1 = p.getInputStream();
                 final InputStream is2 = p.getErrorStream();
                 new Thread() {
                    public void run() {
                       BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
                        try {
                            String line1 = null;
                            while ((line1 = br1.readLine()) != null) {
                                  if (line1 != null){
                                      logger.info("p.getInputStream:"+line1);
                                      if(line1.indexOf("syntax check result:")!=-1){
                                          builder.append(line1);
                                      }
                                  }
                              }
                        } catch (IOException e) {
                             e.printStackTrace();
                        }
                        finally{
                             try {
                               is1.close();
                             } catch (IOException e) {
                                e.printStackTrace();
                            }
                          }
                        }
                     }.start();
                   new Thread() {
                      public void  run() {
                       BufferedReader br2 = new  BufferedReader(new  InputStreamReader(is2));
                          try {
                             String line2 = null ;
                             while ((line2 = br2.readLine()) !=  null ) {
                                  if (line2 != null){
                                  }
                             }
                           } catch (IOException e) {
                                 e.printStackTrace();
                           }
                          finally{
                             try {
                                 is2.close();
                             } catch (IOException e) {
                                 e.printStackTrace();
                             }
                           }
                        }
                      }.start();
                      p.waitFor();
                      p.destroy();
                    } catch (Exception e) {
                            try{
                                p.getErrorStream().close();
                                p.getInputStream().close();
                                p.getOutputStream().close();
                                }
                             catch(Exception ee){}
                   }
        }

java的Process深入讲解

package cn.itcast.process;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

public class ProcessTest implements Runnable{
 private Process process = null;
 public ProcessTest() {
  try {
   process = Runtime.getRuntime().exec("java MyTest");
   new Thread(this).start();

  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 public static void main(String[] args)  {
  ProcessTest processTest = new ProcessTest();
  processTest.send();

 }
 public void send()
 {
  OutputStream outputStream = process.getOutputStream();
  while(true)
  {
   try {
    outputStream.write("this is good\r\n".getBytes());
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 public void run() {
  InputStream inputStream = process.getInputStream();
  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
  String str = null;
  try {
   while(true)
   {
    str = bufferedReader.readLine();
    System.out.println(str);
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

//理解下面这句话就能更加容易的理解上面的代码

在java程序中可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不在连接到键盘和显示器,而是以管道流的形式连接到父进程的

一个输出流和输入流对象上-à好好理解这句代码就能看懂那个程序。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java Process.waitFor()方法详解

    目录 Java Process.waitFor()方法 描述 声明 参数 返回值 异常 实例 process.waitFor()没有作用 Java Process.waitFor()方法 Process.waitFor()方法 将导致当前线程等待,直到该对象的进程结束,才返回调用. 描述 java.lang.Process.waitFor()方法将导致当前的线程等待,如果必要的话,直到由该Process对象表示的进程已经终止.此方法将立即返回,如果子进程已经终止.如果子进程尚未终止,则调用线程将

  • Java Process类的详解及实例代码

    Java Process类的详解 前言: 今天用了下Java.lang.Process类,只是初步的学习,并没有深入实践,因为感觉它的用途并不是很大,偶尔才可能用上,如果要经常使用它的人可以自行参考JDk文档. 对Process类的简要说明: Process类是一个抽象类,方法都是抽象的,它封装了一个进程,也就是一个可执行的程序  该类提供进程的输入.执行输出到进程.等待进程的完成和检查进程的退出状态及销毁进程的方法 ProcessBuilder.start()和Runtime.exec方法创建

  • java process.waitfor返回1的原因及解决

    目录 java process.waitfor返回1 大致的原因如下 process.waitFor()的返回值含义 以下是Linux中返回值对照表 java process.waitfor返回1 java的process,在执行命令时,出现waitfor返回1错误.根据java文档,是operation not permited.但绝大多数情况下,这是瞎扯. 真正原因是,你执行的命令(dos或linux下的命令),java的process执行时候,出错了.而错误本身是在这个命令的字符串上. 大

  • 关于Process的waitFor死锁问题及解决方案

    目录 Process的waitFor死锁问题 1.发现问题 2.原因查找 3.造成死锁原理图 问题代码 解决方案 Java中死锁的简单例子及其避免 我们来看一个死锁的简单例子 那么要怎么预防死锁呢? 下面介绍几个常见方法: Process的waitFor死锁问题 1.发现问题 在实际开发中,进行文件操作时,使用Process对文件进行解压操作,程序执行过程中会出现一直卡在那的问题. 2.原因查找 问题在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞.接着来

  • 调用Process.waitfor导致的进程挂起问题及解决

    目录 问题背景 问题描述 挂起原因 解决方法 JDK上的说明 背后的故事 测试pipe的大小 Linux上pipe分析 问题背景 如果要在Java中调用shell脚本时,可以使用Runtime.exec或ProcessBuilder.start.它们都会返回一个Process对象,通过这个Process可以对获取脚本执行的输出,然后在Java中进行相应处理. 例如,下面的代码: try { Process process = Runtime.getRuntime().exec(cmd); pro

  • Java编程使用Runtime和Process类运行外部程序的方法

    本文实例讲述了Java编程使用Runtime和Process类运行外部程序的方法.分享给大家供大家参考,具体如下: 使用Runtime.getRuntime().exec()方法可以在java程序里运行外部程序. 1. exec(String command) 2. exec(String command, String envp[], File dir) 3. exec(String cmd, String envp[]) 4. exec(String cmdarray[]) 5. exec(

  • Java中Process类的使用与注意事项说明

    目录 Process类的使用与注意事项说明 1.在项目开发中 2.在这里就需要认识一下process类 3.来说说今天业务需求[waitfor()]: 4.前不久遇到一个奇怪的问题就是ajax调用没有返回值 java的Process深入讲解 Process类的使用与注意事项说明 1.在项目开发中 经常会遇到调用其它程序功能的业务需求,在java中通常有两种实现方法 Runtime runtime = Runtime.getRuntime(); Process p = runtime.exec(c

  • Java中Thread类的使用和它的属性

    目录 创建线程 方法一:继承Thread类 方法二:实现Runnable接口中的run()方法 方法三:利用内部类 方法四:使用lambmd表达式 使用线程的好处 Thread类的其他属性和方法 给一个线程起名字 判断一个线程是否存活 Thread的其他常见属性 创建线程 线程的中断 线程的等待 获取线程的引用 线程的休眠 在java中可以进行多线程编程,在java标准库中提供了一个Thread类,来表示线程操作.Thread类可以视为java标准库提供的一组解决多线程编程的一组API. 创建好

  • 详谈java中File类getPath()、getAbsolutePath()、getCanonical的区别

    简单看一下描述,例子最重要. 1.getPath(): 返回定义时的路径,(就是你写什么路径,他就返回什么路径) 2.getAbsolutePath(): 返回绝对路径,但不会处理"."和".."的情况 3.getCanonicalPath(): 返回的是规范化的绝对路径,相当于将getAbsolutePath()中的"."和".."解析成对应的正确的路径 第一个例子:(使用:".\\src\\test.txt&qu

  • 浅谈java中math类中三种取整函数的区别

    math类中三大取整函数 1.ceil 2.floor 3.round 其实三种取整函数挺简单的.只要记住三个函数名翻译过来的汉语便能轻松理解三大函数,下面一一介绍 1.ceil,意思是天花板,java中叫做向上取整,大于等于该数字的最接近的整数 例: math.ceil(13.2)=14 math.ceil(-13.2)=-13 2.floor,意思是地板,java中叫做向下取整,小于等于该数字的最接近的整数 例: math.floor(13.2)=13 math.floor(-13.2)=-

  • 详谈Java中Object类中的方法以及finalize函数作用

    Object是所有类的父类,任何类都默认继承Object. 一.Object类中的方法 1.clone方法 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常. 主要是JAVA里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递,我们有时候不希望在方法里讲参数改变,这是就需要在类中复写clone方法. 2.getClass方法 final方法,获得运行时类型. 3.toString方法 该方法

  • java中Calendar类用法实例详解

    本文实例讲述了java中Calendar类用法.分享给大家供大家参考,具体如下: java中的Calendar在开发中经常被忽略,这篇博客总结一下这个类,对后面项目中使用时期的时候有帮助. Calendar常量(field)的作用 Calendar cal = Calendar.getInstance(); cal.get(Calendar.DATE);//-----------------------当天 1-31 cal.get(Calendar.DAY_OF_MONTH);//------

  • Java中获取类路径classpath的简单方法(推荐)

    如下所示: <SPAN style="FONT-SIZE: 18px"> System.out.println("++++++++++++++++++++++++"); String path = System.getProperty("java.class.path"); String path2 = FreeMarkerWriter.class.getProtectionDomain().getCodeSource().getLo

  • Java中ArrayList类的使用方法

    Java中ArrayList类的用法 1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和IList接口 灵活的设置数组的大小 2.如何使用ArrayList 最简单的例子: ArrayList List = new ArrayList(); for( int i=0;i <10;i++ ) //给数组增加10个Int元素 List.Add(i); //..

  • java arrayList遍历的四种方法及Java中ArrayList类的用法

    java arrayList遍历的四种方法及Java中ArrayList类的用法 package com.test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ArrayListDemo { public static void main(String args[]){ List<String> list = new ArrayList<String

  • Java中Scanner类与BufferReader类的不同点(非常详细)

    java.util.Scanner类是一个简单的文本扫描类,它可以解析基本数据类型和字符串.它本质上是使用正则表达式去读取不同的数据类型. Java.io.BufferedReader类为了能够高效的读取字符序列,从字符输入流和字符缓冲区读取文本. 下面是两个类的不同之处: 当nextLine()被用在nextXXX()之后,用Scanner类有什么问题 尝试去猜测下面代码的输出内容: // Code using Scanner Class import java.util.Scanner; c

随机推荐