IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> API--17--Process -> 正文阅读

[Java知识库]API--17--Process

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


Process

背景

  • 在编写Java程序时,有时候需要在Java程序中执行另外一个程序。
  • 在项目开发中,经常会遇到调用其它程序功能的业务需求

Process是一个抽象类 , 封装了一个进程(即一个执行程序)。

在这里插入图片描述

创建进程两种方式

方式1

Runtime runtime = Runtime.getRuntime();

Process p = runtime.exec(cmd);

方式2

Process p = new ProcessBuilder(cmd).start();

其中:

cmd 是命令行,是一个字符串或者是字符串数组。

  • 不管在哪种操作系统下,程序具有基本类似的一些属性。一个程序启动后就是程序操作系统的一个进程,进程在执行的时候有自己的环境变量、工作目录
  • 能够在Java中执行的外部程序,必须是一个实际存在的可执行文件,对于cmd/shell下的内嵌命令是不能直接执行的,

1. 采用Runtime的exec执行程序时

  • 首先要使用java.lang.Runtime#getRuntime得到一个Runtime实例,然后调用Runtime的exec方法,该方法执行后返回一个Process实例,代表所执行的程序。
  • Runtime提供了多个重载的exec方法,其余的方法都是调用如下核心方法实现的:
    在这里插入图片描述
  • cmdarray:包含要调用的命令及其参数的数组
  • envp:环境变量,其中每个元素的环境变量设置格式为name = value,如果子进程应该继承当前进程的环境,则为null。
  • dir:子进程的工作目录,如果子进程应该继承当前进程的工作目录,则为null。

2. 采用ProcessBuilder类启动一个新的程序

在这里插入图片描述

API–18–ProcessBuilder

process类: api 方法

在这里插入图片描述

1.destroy()

杀掉子进程。

 /**
     * 杀死子进程,子进程是否立即终止取决于实现
     */
    public abstract void destroy();

    /**
     * 强制杀死子进程
     * @return
     */
    public java.lang.Process destroyForcibly() {
        destroy();
        return this;
    }


2.isAlive()

判断子进程是否存活

在这里插入图片描述

3.exitValue()

返回子进程退出的值

  • 只有启动的进程执行完成、或者由于异常退出后,exitValue方法才会有正常的返回值,否则抛出异常。
    在这里插入图片描述

4.getOutputStream(),

连接到子进程的输出流

  • 可以从该流中读取子进程的标准输出

5.getInputStream()

连接到子进程的输入流

  • 写入到该流中的数据作为子进程的标准输入

6.getErrorStream ()

连接到子进程的错误流

  • 获取子进程的错误输出流。如果错误输出被重定向,则不能从该流中读取错误输出。
   /**
     * 连接到子进程的输出流
     * @return
     */
    public abstract OutputStream getOutputStream();

    /**
     * 连接到子进程的输入流
     * @return
     */
    public abstract InputStream getInputStream();

    /**
     * 连接到子进程的错误流
     * @return
     */
    public abstract InputStream getErrorStream();

7.waitFor()

导致当前线程等待

  • 导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。通过该类提供的方法,可以实现与启动的进程之间通信,达到交互的目的。
  • 使当前线程等待,直到子进程退出或者超时
  /**
     * 使当前线程在必要时等待,直到此Process对象表示的进程已终止
     * 如果子进程已经中止,此方法立即返回
     * 如果子进程还没有中止,正在调用的线程将被阻塞,直到子进程退出。
     * @return
     * @throws InterruptedException
     */
    public abstract int waitFor() throws InterruptedException;

    /**
     * 使当前线程等待,直到子进程退出或者超时
     * @param timeout
     * @param unit
     * @return
     * @throws InterruptedException
     */
    public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException{
        long startTime = System.nanoTime();
        long rem = unit.toNanos(timeout);

        do {
            try {
                exitValue();
                return true;
            } catch(IllegalThreadStateException ex) {
                if (rem > 0)
                    Thread.sleep(
                            Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
            }
            rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
        } while (rem > 0);
        return false;
    }


Process 应用案例

1. 从标准输出和错误输出流读取信息

  • 从启动其他进程的Java进程看,已启动的其他进程的输出就是一个普通的输入流,可以通过getInputStream和getErrorStream来获取。
  • 对于一般输出文本的进程来说,可以将InputStream封装成BufferedReader,然后就可以一行一行的对进程的标准输出进行处理。

通过Runtime实现

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
 
class ProcessTest1 {
    public static void main(String[] args) {
        try {
            String line = null;
 
            //list the files and directorys under C:\
            Process p = Runtime.getRuntime().exec("CMD.exe /C dir", null, new File("C:\\"));
            BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream(), "GBK"));
            while ((line = stdout.readLine()) != null) {
                System.out.println(line);
            }
            stdout.close();
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class test01 {

    public static void main(String[] args) {

        //echo the value of NAME
        try {
            String line = null;
            Process p = Runtime.getRuntime().exec("CMD.exe /C echo %NAME%", new String[]{"NAME=TEST!!!!"});
            BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = stdout.readLine()) != null) {
                System.out.println(line);
            }
            stdout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

在这里插入图片描述

通过ProcessBuilder实现

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
 
public class ProcessTest2 {
    public static void main(String[] args) {
        try {
            String line = null;
            BufferedReader stdout = null;
 
            List list = new ArrayList();
            //list the files and directorys under C:\
            list.add("CMD.EXE");
            list.add("/C");
            list.add("dir");
            ProcessBuilder pb = new ProcessBuilder(list);
            pb.directory(new File("C:\\"));
            Process p = pb.start();
 
            stdout = new BufferedReader(new InputStreamReader(p.getInputStream(),"GBK"));
            while ((line = stdout.readLine()) != null) {
                System.out.println(line);
            }
            stdout.close();
 
            //echo the value of NAME
            pb = new ProcessBuilder();
            pb.command(new String[]{"CMD.exe", "/C", "echo %NAME%"});
            pb.environment().put("NAME", "TEST");
            p = pb.start();
            stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = stdout.readLine()) != null) {
                System.out.println(line);
            }
            stdout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.获取进程的返回值

通常,一个程序/进程在执行结束后会向操作系统返回一个整数值,0一般代表执行成功,非0表示执行出现问题。

有两种方式可以用来获取进程的返回值:

  • 一是利用waitFor(),该方法是阻塞的,直到进程执行完成后再返回。该方法返回一个代表进程返回值的整数值;
  • 另一个方法是调用exitValue()方法,该方法是非阻塞的,调用立即返回。但是如果进程没有执行完成,则抛出异常。

3.执行shell中的命令示例

案例1:

业务需求:

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

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


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class test01 {

    public static void main(String[] args){

        String source ="/approot1/recive";
        String target="/approot1/temp";
        String file="/approot1/temp/xx.bin'";
        String jar="XXXX";
        
        String copy="cp -rf "+source+" "+target;
        String jar="jar -uvf "+jar+" "+file;
        
        cmd(copy);
        cmd(jar);

    }


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

        }
    }

}

案例2:

是无法直接执行shell中的命令的,如果直接执行ls /home命令会报‘java.io.IOException: Cannot run program “ls /home”: error=2, No such file or directory’的错误,参见如下代码示例。

public class ProcessTest3 {
 
    public static void main(String[] args) {
        try {
            String line;
            ProcessBuilder pb = new ProcessBuilder();
            /*
            * pb.command("ls /home");
            * 如上执行报错:java.io.IOException: Cannot run program "ls /home": error=2, No such file or directory
            * 
            * pb.command("bash", "-c", "ls ", "/home");
            * 如上执行,查看的不是/home路径下的文件,而是当前运行目录下的文件
            * */
            pb.command("bash", "-c", "ls /home");
            //merge the error output with the standard output
            pb.redirectErrorStream(true);
            Process p = pb.start();
 
            //read the standard output
            BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = stdout.readLine()) != null) {
                System.out.println(line);
            }
 
            int ret = p.waitFor();
            System.out.println("the return code is " + ret);
            stdout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

案例3:

public static void restart() throws IOException {
		// Runtime 例子
		Process p;
		// test.bat中的命令是ipconfig/all
		String cmd = "c:\\test\\test.bat";
 
		try {
			// 执行命令
			p = Runtime.getRuntime().exec(cmd);
			// 取得命令结果的输出流
			InputStream fis = p.getInputStream();
			// 用一个读输出流类去读
			InputStreamReader isr = new InputStreamReader(fis);
			// 用缓冲器读行
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			// 直到读完为止
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
}

案例4:

public static void restart() throws IOException {
       // ProcessBuilder 例子 Java程序自重启
		try {
	
		// 用一条指定的命令去构造一个进程生成器
		ProcessBuilder pb = new ProcessBuilder("java", "-jar", "Test3.jar");
		// 让这个进程的工作区空间改为F:\dist
		// 这样的话,它就会去F:\dist目录下找Test.jar这个文件
		pb.directory(new File("F:\\dist"));
		// 得到进程生成器的环境 变量,这个变量我们可以改,
		// 改了以后也会反应到新起的进程里面去
		Map<String, String> map = pb.environment();
		Process p1 = pb.start();
		// 然后就可以对p做自己想做的事情了
		// 自己这个时候就可以退出了
		System.exit(0);
		
	    } catch (IOException e) {
			e.printStackTrace();
		}
}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:04:09  更:2022-05-05 11:06:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:20:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码