1 需求
- Runtime类 对应实物就是下面这个
- 运行中直接运行cmd、notepad、mspaint、calc等是ok的
- 运行中直接运行dir等会报错
- Java通过Runtime.getRuntime().exec()创建子进程是入参字符串中首个程序,比如:cmd /c ping www.baidu.com,cmd.exe是Runtime.getRuntime().exec()创建的子进程,Process类的isAlive、exitValue、waitFor、destroy都是根据cmd.exe执行情况判断的,而不是PING.exe。
注意:如果想控制PING.EXE执行情况,直接exec("ping www.baidu.com')
- idea64.exe
- java.exe:主进程
- cmd.exe:Runtime.getRuntime().exec()创建的子进程
- PING.EXE
- 需求:cmd命令、start命令
- cmd命令 c参数、k参数
- start命令 b参数
……
- Runtime类
- Process类
- InputStream类
- InputStreamReader类
- BufferedReader类
- 需求1:仅执行CMD命令,并不需要获取命令执行结果;
- 需求2:执行CMD命令,同时只需要命令执行结果的某一行;
- 需求3:执行CMD命令,需要命令执行结果所有数据;
- 需求:判断子进程是否结束
- 解决方案1:Process.isAlive()
- 解决方案2:Process.exitValue()
- 循环执行同一条CMD命令,第一次循环命令执行结束后,才允许执行第二次循环;
- Process类的exitValue方法:非线程阻塞
- Process类的waitFor方法:线程阻塞,如果子进程没有执行完毕,主线程会一直阻塞;
- Process类的isAlive方法:
- 参考资料:java runtime exec 输出
- 需求:子进程等待
- 解决方案1:Process.waitFor()
- 解决方案2:Thread.sleep()
- 解决方案3:timeout命令
- 需求:停止子进程停止
- 需求:停止子进程树
- 需求:主进程和子进程死锁
- 解决方案1:Process.getErrorStream()
- 循环执行同一条CMD命令,第一次循环执行结束后,延迟N秒再执行第二次循环;
- Windows的TIMEOUT命令:无法满足需求,使用Process类的getErrorStream()方法,获取错误信息如下:
- 错误: 不支持输入重新定向,立即退出此进程。
- 需求5:一次执行多条CMD命令,同时获取所有命令执行结果;
2 接口
Class Runtime
public class Runtime extends Object
java.lang.Object
java.lang.Runtime
- Method Detail
- public static Runtime getRuntime()
- public void exit(int status)
- public void addShutdownHook(Thread hook)
- public boolean removeShutdownHook(Thread hook)
- public void halt(int status)
- public Process exec(String command) throws IOException
- public Process exec(String command, String[] envp) throws IOException
- public Process exec(String command, String[] envp, File dir) throws IOException
- public Process exec(String[] cmdarray) throws IOException
- public Process exec(String[] cmdarray, String[] envp) throws IOException
- public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException
- public int availableProcessors()
- public long freeMemory()
- public long totalMemory()
- public long maxMemory()
- public void gc()
- public void runFinalization()
- public void traceInstructions(boolean on)
- public void traceMethodCalls(boolean on)
- public void load(String filename)
- public void loadLibrary(String libname)
3.1 示例代码:直接调起记事本,不需要获取命令执行结果
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("notepad");
process.waitFor();
System.out.println(process.isAlive());
System.out.println(process.exitValue());
}
}
3.2 示例代码:执行命令,并且获取命令执行结果,但执行结果只有一行
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) {
try {
Process process = Runtime.getRuntime().exec("cmd /c adb shell getprop ro.build.fingerprint");
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.3 示例代码:执行命令,并且获取命令执行结果,但执行结果有多行
Runtime类
Process类
InputStream类:输入字节流
InputStreamReader类:字节流转化成字符流
BufferedReader类:使用缓冲流
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
// Runtime类
Runtime runtime = Runtime.getRuntime();
// Process类
Process process = runtime.exec("ipconfig");
// InputStream类
InputStream inputStream = process.getInputStream();
// InputStreamReader类
InputStreamReader reader = new InputStreamReader(inputStream, "GBK");
// BufferedReader类
BufferedReader br = new BufferedReader(reader);
String tmp = null;
while ((tmp = br.readLine()) != null) {
System.out.println(tmp);
}
}
}
3.4 示例代码:执行多条CMD命令,同时获取所有命令执行结果
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
// Windows命令连接符:&&
Process process = Runtime.getRuntime().exec("cmd /c dir&&ipconfig");
InputStreamReader reader = new InputStreamReader(process.getInputStream(), "GBK");
BufferedReader br = new BufferedReader(reader);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
3.5 示例代码:顺序执行多条CMD命令,如果某条命令运行时间较长,需要等待完成后再执行下一条
3.X 示例:循环执行同一条CMD命令,第一次循环执行结束后,延迟N秒再执行第二次循环
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 预期结果:输出1,延迟3秒,输出2。
* 实际结果:timeout命令没有执行成功,调用getErrorStream(),获取错误信息如下:
* 错误: 不支持输入重新定向,立即退出此进程。
*/
public class Test {
public static void main(String[] args) {
System.out.println(1);
try {
Process process = Runtime.getRuntime().exec("cmd /c timeout 10");
// Process类的getInputStream()、getErrorStream()方法区别
InputStreamReader ir = new InputStreamReader(process.getErrorStream(), "GBK");
BufferedReader br = new BufferedReader(ir);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
ir.close();
// Process.exitValue()返回值0,命令执行正常;非0,命令执行异常
System.out.println("cmd /c timeout 10 命令是否执行成功: " + process.exitValue());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(2);
}
}